home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Multimedia / Movie3.0 / Source / mpegDecode / video.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-08  |  103.3 KB  |  3,932 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.  
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  *
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. /* This file contains C code that implements
  22.  * the video decoder model.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <assert.h>
  28.  
  29. #ifndef MIPS
  30. #include <sys/time.h>
  31. #else
  32. #include <sys/types.h>
  33. #include <sys/system.h>
  34. #endif
  35.  
  36. #include "decoders.h"
  37. #include "video.h"
  38. #include "util.h"
  39. #include "proto.h"
  40.  
  41. /* Declarations of functions. */
  42. static void ReconIMBlock();
  43. static void ReconPMBlock();
  44. static void ReconBMBlock();
  45. static void ReconBiMBlock();
  46. static void ReconSkippedBlock();
  47. static void DoPictureDisplay();
  48. static int ParseSeqHead();
  49. static int ParseGOP();
  50. static int ParsePicture();
  51. static int ParseSlice();
  52. static int ParseMacroBlock();
  53. static void ProcessSkippedPFrameMBlocks();
  54. static void ProcessSkippedBFrameMBlocks();
  55.  
  56. extern int ditherType;
  57. char *ditherFlags;
  58.  
  59. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  60.  
  61. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  62.  
  63. /* Declare global pointer to vid stream used for current decoding. */
  64.  
  65. VidStream *curVidStream = NULL;
  66.  
  67. /* Set up array for fast conversion from zig zag order to row/column
  68.    coordinates.
  69. */
  70.  
  71. int zigzag[64][2] = {
  72.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  73.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  74.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  75.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  76.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  77. 7, 5, 7, 6, 6, 7, 7, 7};
  78. /* Array mapping zigzag to array pointer offset. */
  79.  
  80. int zigzag_direct[64] = {
  81.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  82.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  83.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  84. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  85. /* Set up array for fast conversion from row/column coordinates to
  86.    zig zag order.
  87. */
  88.  
  89. int scan[8][8] = {
  90.   {0, 1, 5, 6, 14, 15, 27, 28},
  91.   {2, 4, 7, 13, 16, 26, 29, 42},
  92.   {3, 8, 12, 17, 25, 30, 41, 43},
  93.   {9, 11, 18, 24, 31, 40, 44, 53},
  94.   {10, 19, 23, 32, 39, 45, 52, 54},
  95.   {20, 22, 33, 38, 46, 51, 55, 60},
  96.   {21, 34, 37, 47, 50, 56, 59, 61},
  97. {35, 36, 48, 49, 57, 58, 62, 63}};
  98. /* Initialize P and B skip flags. */
  99.  
  100. static int No_P_Flag = 0;
  101. static int No_B_Flag = 0;
  102.  
  103. /* Max lum, chrom indices for illegal block checking. */
  104.  
  105. static int lmaxx;
  106. static int lmaxy;
  107. static int cmaxx;
  108. static int cmaxy;
  109.  
  110. /*
  111.  * We use a lookup table to make sure values stay in the 0..255 range.
  112.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  113.  * table the "crop table".
  114.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  115.  */
  116.  
  117. #define MAX_NEG_CROP 384
  118. #define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)
  119. #define assertCrop(x)    assert(((x) >= -MAX_NEG_CROP) && \
  120.                    ((x) <= 256+MAX_NEG_CROP))
  121. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  122.  
  123. /*
  124.   The following accounts for time and size  spent in various parsing acitivites
  125.   if ANALYSIS has been defined.
  126. */
  127.  
  128. #ifdef ANALYSIS
  129.  
  130.  
  131. unsigned int bitCount = 0;
  132.  
  133. int showmb_flag = 0;
  134. int showEachFlag = 0;
  135.  
  136. typedef struct {
  137.   int frametype;
  138.   unsigned int totsize;
  139.   unsigned int number;
  140.   unsigned int i_mbsize;
  141.   unsigned int p_mbsize;
  142.   unsigned int b_mbsize;
  143.   unsigned int bi_mbsize;
  144.   unsigned int i_mbnum;
  145.   unsigned int p_mbnum;
  146.   unsigned int b_mbnum;
  147.   unsigned int bi_mbnum;
  148.   unsigned int i_mbcbp[64];
  149.   unsigned int p_mbcbp[64];
  150.   unsigned int b_mbcbp[64];
  151.   unsigned int bi_mbcbp[64];
  152.   unsigned int i_mbcoeff[64];
  153.   unsigned int p_mbcoeff[64];
  154.   unsigned int b_mbcoeff[64];
  155.   unsigned int bi_mbcoeff[64];
  156.   double tottime;
  157. } Statval;
  158.  
  159. Statval stat_a[4];
  160. unsigned int pictureSizeCount;
  161. unsigned int mbSizeCount;
  162. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  163. unsigned int cacheHit[8][8];
  164. unsigned int cacheMiss[8][8];
  165.  
  166. static void
  167. init_stat_struct(astat)
  168.   Statval *astat;
  169. {
  170.   int j;
  171.  
  172.   astat->frametype = 0;
  173.   astat->totsize = 0;
  174.   astat->number = 0;
  175.   astat->i_mbsize = 0;
  176.   astat->p_mbsize = 0;
  177.   astat->b_mbsize = 0;
  178.   astat->bi_mbsize = 0;
  179.   astat->i_mbnum = 0;
  180.   astat->p_mbnum = 0;
  181.   astat->b_mbnum = 0;
  182.   astat->bi_mbnum = 0;
  183.  
  184.   for (j = 0; j < 64; j++) {
  185.  
  186.     astat->i_mbcbp[j] = 0;
  187.     astat->p_mbcbp[j] = 0;
  188.     astat->b_mbcbp[j] = 0;
  189.     astat->bi_mbcbp[j] = 0;
  190.     astat->i_mbcoeff[j] = 0;
  191.     astat->p_mbcoeff[j] = 0;
  192.     astat->b_mbcoeff[j] = 0;
  193.     astat->bi_mbcoeff[j] = 0;
  194.   }
  195.   astat->tottime = 0.0;
  196. }
  197.  
  198. void
  199. init_stats()
  200. {
  201.   int i, j;
  202.  
  203.   for (i = 0; i < 4; i++) {
  204.     init_stat_struct(&(stat_a[i]));
  205.     stat_a[i].frametype = i;
  206.   }
  207.  
  208.   for (i = 0; i < 8; i++) {
  209.     for (j = 0; j < 8; j++) {
  210.       cacheHit[i][j] = 0;
  211.       cacheMiss[i][j] = 0;
  212.     }
  213.   }
  214.  
  215.   bitCount = 0;
  216. }
  217.  
  218. static void
  219. PrintOneStat()
  220. {
  221.   int i;
  222.  
  223.   printf("\n");
  224.   switch (stat_a[0].frametype) {
  225.   case I_TYPE:
  226.     printf("I FRAME\n");
  227.     break;
  228.   case P_TYPE:
  229.     printf("P FRAME\n");
  230.     break;
  231.   case B_TYPE:
  232.     printf("B FRAME\n");
  233.     break;
  234.   }
  235.  
  236.   printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8);
  237.   if (stat_a[0].i_mbnum > 0) {
  238.     printf("\tI Macro Block Stats:\n");
  239.     printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum);
  240.     printf("\tAvg. Size: %d bytes + %d bits\n",
  241.        stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum),
  242.        (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8);
  243.     printf("\t\tCoded Block Pattern Histogram:\n");
  244.     for (i = 0; i < 64; i += 8) {
  245.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i],
  246.          stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3],
  247.          stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6],
  248.          stat_a[0].i_mbcbp[i + 7]);
  249.     }
  250.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  251.     for (i = 0; i < 64; i += 8) {
  252.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i],
  253.          stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2],
  254.          stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4],
  255.          stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6],
  256.          stat_a[0].i_mbcoeff[i + 7]);
  257.     }
  258.   }
  259.   if (stat_a[0].p_mbnum > 0) {
  260.     printf("\tP Macro Block Stats:\n");
  261.     printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum);
  262.     printf("\tAvg. Size: %d bytes + %d bits\n",
  263.        stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum),
  264.        (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8);
  265.     printf("\t\tCoded Block Pattern Histogram:\n");
  266.     for (i = 0; i < 64; i += 8) {
  267.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i],
  268.          stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3],
  269.          stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6],
  270.          stat_a[0].p_mbcbp[i + 7]);
  271.     }
  272.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  273.     for (i = 0; i < 64; i += 8) {
  274.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i],
  275.          stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2],
  276.          stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4],
  277.          stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6],
  278.          stat_a[0].p_mbcoeff[i + 7]);
  279.     }
  280.   }
  281.   if (stat_a[0].b_mbnum > 0) {
  282.     printf("\tB Macro Block Stats:\n");
  283.     printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum);
  284.     printf("\tAvg. Size: %d bytes + %d bits\n",
  285.        stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum),
  286.        (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8);
  287.     printf("\t\tCoded Block Pattern Histogram:\n");
  288.     for (i = 0; i < 64; i += 8) {
  289.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i],
  290.          stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3],
  291.          stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6],
  292.          stat_a[0].b_mbcbp[i + 7]);
  293.     }
  294.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  295.     for (i = 0; i < 64; i += 8) {
  296.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i],
  297.          stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2],
  298.          stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4],
  299.          stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6],
  300.          stat_a[0].b_mbcoeff[i + 7]);
  301.     }
  302.   }
  303.   if (stat_a[0].bi_mbnum > 0) {
  304.     printf("\tBi Macro Block Stats:\n");
  305.     printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum);
  306.     printf("\tAvg. Size: %d bytes + %d bits\n",
  307.        stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum),
  308.        (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8);
  309.     printf("\t\tCoded Block Pattern Histogram:\n");
  310.     for (i = 0; i < 64; i += 8) {
  311.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i],
  312.          stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3],
  313.          stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6],
  314.          stat_a[0].bi_mbcbp[i + 7]);
  315.     }
  316.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  317.     for (i = 0; i < 64; i += 8) {
  318.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i],
  319.          stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2],
  320.          stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4],
  321.          stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6],
  322.          stat_a[0].bi_mbcoeff[i + 7]);
  323.     }
  324.   }
  325.   printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime);
  326.   printf("****************\n");
  327. }
  328.  
  329. void
  330. PrintAllStats()
  331. {
  332.   int i, j;
  333.   unsigned int supertot, supernum;
  334.   double supertime;
  335.  
  336.   printf("\n");
  337.   printf("General Info: \n");
  338.   printf("Width: %d\nHeight: %d\n", curVidStream->mb_width * 16, curVidStream->mb_height * 16);
  339.  
  340.   for (i = 1; i < 4; i++) {
  341.  
  342.     if (stat_a[i].number == 0)
  343.       continue;
  344.  
  345.     switch (i) {
  346.     case 1:
  347.       printf("I FRAMES\n");
  348.       break;
  349.     case 2:
  350.       printf("P FRAMES\n");
  351.       break;
  352.     case 3:
  353.       printf("B FRAMES\n");
  354.       break;
  355.     }
  356.  
  357.     printf("Number: %d\n", stat_a[i].number);
  358.     printf("Avg. Size: %d bytes + %d bits\n",
  359.        stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8);
  360.     if (stat_a[i].i_mbnum > 0) {
  361.       printf("\tI Macro Block Stats:\n");
  362.       printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum);
  363.       printf("\tAvg. Size: %d bytes + %d bits\n",
  364.          stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum),
  365.          (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8);
  366.       printf("\t\tCoded Block Pattern Histogram:\n");
  367.       for (j = 0; j < 64; j += 8) {
  368.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j],
  369.            stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3],
  370.            stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6],
  371.            stat_a[i].i_mbcbp[j + 7]);
  372.       }
  373.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  374.       for (j = 0; j < 64; j += 8) {
  375.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j],
  376.            stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2],
  377.            stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4],
  378.            stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6],
  379.            stat_a[i].i_mbcoeff[j + 7]);
  380.       }
  381.     }
  382.     if (stat_a[i].p_mbnum > 0) {
  383.       printf("\tP Macro Block Stats:\n");
  384.       printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum);
  385.       printf("\tAvg. Size: %d bytes + %d bits\n",
  386.          stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum),
  387.          (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8);
  388.       printf("\t\tCoded Block Pattern Histogram:\n");
  389.       for (j = 0; j < 64; j += 8) {
  390.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j],
  391.            stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3],
  392.            stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6],
  393.            stat_a[i].p_mbcbp[j + 7]);
  394.       }
  395.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  396.       for (j = 0; j < 64; j += 8) {
  397.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j],
  398.            stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2],
  399.            stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4],
  400.            stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6],
  401.            stat_a[i].p_mbcoeff[j + 7]);
  402.       }
  403.     }
  404.     if (stat_a[i].b_mbnum > 0) {
  405.       printf("\tB Macro Block Stats:\n");
  406.       printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum);
  407.       printf("\tAvg. Size: %d bytes + %d bits\n",
  408.          stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum),
  409.          (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8);
  410.       printf("\t\tCoded Block Pattern Histogram:\n");
  411.       for (j = 0; j < 64; j += 8) {
  412.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j],
  413.            stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3],
  414.            stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6],
  415.            stat_a[i].b_mbcbp[j + 7]);
  416.       }
  417.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  418.       for (j = 0; j < 64; j += 8) {
  419.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j],
  420.            stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2],
  421.            stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4],
  422.            stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6],
  423.            stat_a[i].b_mbcoeff[j + 7]);
  424.       }
  425.     }
  426.     if (stat_a[i].bi_mbnum > 0) {
  427.       printf("\tBi Macro Block Stats:\n");
  428.       printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum);
  429.       printf("\tAvg. Size: %d bytes + %d bits\n",
  430.          stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum),
  431.          (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8);
  432.       printf("\t\tCoded Block Pattern Histogram:\n");
  433.       for (j = 0; j < 64; j += 8) {
  434.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j],
  435.            stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3],
  436.            stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6],
  437.            stat_a[i].bi_mbcbp[j + 7]);
  438.       }
  439.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  440.       for (j = 0; j < 64; j += 8) {
  441.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j],
  442.            stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2],
  443.            stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4],
  444.            stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6],
  445.            stat_a[i].bi_mbcoeff[j + 7]);
  446.       }
  447.     }
  448.     printf("\nAvg. Time to Decode: %f secs.\n",
  449.        (stat_a[i].tottime / ((double) stat_a[i].number)));
  450.     printf("\n");
  451.     printf("*************************\n\n");
  452.   }
  453.  
  454.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  455.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  456.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  457.  
  458.   printf("Total Number of Frames: %d\n", supernum);
  459.   printf("Avg Frame Size: %d bytes %d bits\n",
  460.      supertot / (8 * supernum), (supertot / supernum) % 8);
  461.   printf("Total Time Decoding: %g secs.\n", supertime);
  462.   printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
  463.   printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime);
  464.   printf("\n");
  465.  
  466.   printf("Cache Hits/Miss\n");
  467.   for (i = 0; i < 8; i++) {
  468.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  469.        cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1],
  470.        cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]);
  471.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  472.        cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5],
  473.        cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]);
  474.   }
  475.  
  476. }
  477.  
  478. static void
  479. CollectStats()
  480. {
  481.   int i, j;
  482.  
  483.   i = stat_a[0].frametype;
  484.  
  485.   stat_a[i].totsize += stat_a[0].totsize;
  486.   stat_a[i].number += stat_a[0].number;
  487.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  488.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  489.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  490.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  491.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  492.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  493.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  494.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  495.  
  496.   for (j = 0; j < 64; j++) {
  497.  
  498.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  499.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  500.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  501.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  502.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  503.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  504.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  505.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  506.   }
  507.  
  508.   stat_a[i].tottime += stat_a[0].tottime;
  509.  
  510.   init_stat_struct(&(stat_a[0]));
  511. }
  512.  
  513. static unsigned int
  514. bitCountRead()
  515. {
  516.   return bitCount;
  517. }
  518.  
  519. static void
  520. StartTime()
  521. {
  522.   stat_a[0].tottime = ReadSysClock();
  523. }
  524.  
  525. static void
  526. EndTime()
  527. {
  528.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  529. }
  530. #endif
  531.  
  532. double realTimeStart;
  533. int totNumFrames = 0;
  534.  
  535. double
  536. ReadSysClock()
  537. {
  538.   struct timeval tv;
  539.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  540.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  541. }
  542.  
  543. void
  544. PrintTimeInfo()
  545. {
  546.   double spent;
  547.  
  548.   spent = ReadSysClock() - realTimeStart;
  549. }
  550.  
  551.  
  552.  
  553. /*
  554.  *--------------------------------------------------------------
  555.  *
  556.  * NewVidStream --
  557.  *
  558.  *    Allocates and initializes a VidStream structure. Takes
  559.  *      as parameter requested size for buffer length.
  560.  *
  561.  * Results:
  562.  *    A pointer to the new VidStream structure.
  563.  *
  564.  * Side effects:
  565.  *      None.
  566.  *
  567.  *--------------------------------------------------------------
  568.  */
  569.  
  570. VidStream *
  571. NewVidStream(bufLength)
  572.   int bufLength;
  573. {
  574.   int i, j;
  575.   VidStream *new;
  576.   static unsigned char default_intra_matrix[64] = {
  577.     8, 16, 19, 22, 26, 27, 29, 34,
  578.     16, 16, 22, 24, 27, 29, 34, 37,
  579.     19, 22, 26, 27, 29, 34, 34, 38,
  580.     22, 22, 26, 27, 29, 34, 37, 40,
  581.     22, 26, 27, 29, 32, 35, 40, 48,
  582.     26, 27, 29, 32, 35, 40, 48, 58,
  583.     26, 27, 29, 34, 38, 46, 56, 69,
  584.   27, 29, 35, 38, 46, 56, 69, 83};
  585.  
  586.   /* Check for legal buffer length. */
  587.  
  588.   if (bufLength < 4)
  589.     return NULL;
  590.  
  591.   /* Make buffer length multiple of 4. */
  592.  
  593.   bufLength = (bufLength + 3) >> 2;
  594.  
  595.   /* Allocate memory for new structure. */
  596.  
  597.   new = (VidStream *) malloc(sizeof(VidStream));
  598.  
  599.   /* Initialize pointers to extension and user data. */
  600.  
  601.   new->group.ext_data = new->group.user_data =
  602.     new->picture.extra_info = new->picture.user_data =
  603.     new->picture.ext_data = new->slice.extra_info =
  604.     new->ext_data = new->user_data = NULL;
  605.  
  606.   /* Copy default intra matrix. */
  607.  
  608.   for (i = 0; i < 8; i++) {
  609.     for (j = 0; j < 8; j++) {
  610.       new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];
  611.     }
  612.   }
  613.  
  614.   /* Initialize crop table. */
  615.  
  616.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  617.     if (i <= 0) {
  618.       cropTbl[i + MAX_NEG_CROP] = 0;
  619.     } else if (i >= 255) {
  620.       cropTbl[i + MAX_NEG_CROP] = 255;
  621.     } else {
  622.       cropTbl[i + MAX_NEG_CROP] = i;
  623.     }
  624.   }
  625.  
  626.   /* Initialize non intra quantization matrix. */
  627.  
  628.   for (i = 0; i < 8; i++) {
  629.     for (j = 0; j < 8; j++) {
  630.       new->non_intra_quant_matrix[j][i] = 16;
  631.     }
  632.   }
  633.  
  634.   /* Initialize pointers to image spaces. */
  635.  
  636.   new->current = new->past = new->future = NULL;
  637.   for (i = 0; i < RING_BUF_SIZE; i++) {
  638.     new->ring[i] = NULL;
  639.   }
  640.  
  641.   /* Create buffer. */
  642.  
  643.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  644.  
  645.   /*
  646.    * Set max_buf_length to one less than actual length to deal with messy
  647.    * data without proper seq. end codes.
  648.    */
  649.  
  650.   new->max_buf_length = bufLength - 1;
  651.  
  652.   /* Initialize bitstream i/o fields. */
  653.  
  654.   new->bit_offset = 0;
  655.   new->buf_length = 0;
  656.   new->buffer = new->buf_start;
  657.  
  658.  
  659.   /* Return structure. */
  660.  
  661.   return new;
  662. }
  663.  
  664.  
  665.  
  666. /*
  667.  *--------------------------------------------------------------
  668.  *
  669.  * DestroyVidStream --
  670.  *
  671.  *    Deallocates a VidStream structure.
  672.  *
  673.  * Results:
  674.  *      None.
  675.  *
  676.  * Side effects:
  677.  *    None.
  678.  *
  679.  *--------------------------------------------------------------
  680.  */
  681. void
  682. DestroyVidStream(astream)
  683.   VidStream *astream;
  684. {
  685.   int i;
  686.  
  687.   if (astream->ext_data != NULL)
  688.     free(astream->ext_data);
  689.  
  690.   if (astream->user_data != NULL)
  691.     free(astream->user_data);
  692.  
  693.   if (astream->group.ext_data != NULL)
  694.     free(astream->group.ext_data);
  695.  
  696.   if (astream->group.user_data != NULL)
  697.     free(astream->group.user_data);
  698.  
  699.   if (astream->picture.extra_info != NULL)
  700.     free(astream->picture.extra_info);
  701.  
  702.   if (astream->picture.ext_data != NULL)
  703.     free(astream->picture.ext_data);
  704.  
  705.   if (astream->picture.user_data != NULL)
  706.     free(astream->picture.user_data);
  707.  
  708.   if (astream->slice.extra_info != NULL)
  709.     free(astream->slice.extra_info);
  710.  
  711.   if (astream->buf_start != NULL)
  712.     free(astream->buf_start);
  713.  
  714.   for (i = 0; i < RING_BUF_SIZE; i++) {
  715.     if (astream->ring[i] != NULL) {
  716.       DestroyPictImage(astream->ring[i]);
  717.       astream->ring[i] = NULL;
  718.     }
  719.   }
  720.  
  721.   free((char *) astream);
  722. }
  723.  
  724.  
  725.  
  726.  
  727. /*
  728.  *--------------------------------------------------------------
  729.  *
  730.  * NewPictImage --
  731.  *
  732.  *    Allocates and initializes a PictImage structure.
  733.  *      The width and height of the image space are passed in
  734.  *      as parameters.
  735.  *
  736.  * Results:
  737.  *    A pointer to the new PictImage structure.
  738.  *
  739.  * Side effects:
  740.  *    None.
  741.  *
  742.  *--------------------------------------------------------------
  743.  */
  744.  
  745. PictImage *
  746. NewPictImage(width, height)
  747.   unsigned int width, height;
  748. {
  749.   PictImage *new;
  750.  
  751.   /* Allocate memory space for new structure. */
  752.  
  753.   new = (PictImage *) malloc(sizeof(PictImage));
  754.  
  755.  
  756.   /* Allocate memory for image spaces. */
  757.  
  758. #ifdef SH_MEM
  759.   new->ximage = NULL;
  760.  
  761.   if (shmemFlag) {
  762.     Visual *fc_visual;
  763.     int depth;
  764.     Visual *FindFullColorVisual();
  765.  
  766.     if (ditherType == FULL_COLOR_DITHER) {
  767.       fc_visual = FindFullColorVisual(display, &depth);
  768.       new->ximage = XShmCreateImage(display, fc_visual, depth, ZPixmap,
  769.                     NULL, &(new->shminfo), width, height);
  770.     } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
  771.       new->ximage = XShmCreateImage(display, None, 1, XYBitmap,
  772.                     NULL, &(new->shminfo), width, height);
  773.     } else {
  774.       new->ximage = XShmCreateImage(display, None, 8, ZPixmap, NULL,
  775.                     &(new->shminfo), width, height);
  776.     }
  777.  
  778.     /* If no go, then revert to normal Xlib calls. */
  779.  
  780.     if (new->ximage == NULL) {
  781.       shmemFlag = 0;
  782.       goto shmemerror;
  783.     }
  784.     /* Success here, continue. */
  785.  
  786.     new->shminfo.shmid = shmget(IPC_PRIVATE, (new->ximage->bytes_per_line *
  787.                           new->ximage->height),
  788.                 IPC_CREAT | 0777);
  789.  
  790.     if (new->shminfo.shmid < 0) {
  791.       XDestroyImage(new->ximage);
  792.       new->ximage = NULL;
  793.       shmemFlag = 0;
  794.       goto shmemerror;
  795.     }
  796.     new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0);
  797.     if (new->shminfo.shmaddr == ((char *) -1)) {
  798.       XDestroyImage(new->ximage);
  799.       new->ximage = NULL;
  800.       shmemFlag = 0;
  801.       goto shmemerror;
  802.     }
  803.     new->ximage->data = new->shminfo.shmaddr;
  804.     new->display = (unsigned char *) new->ximage->data;
  805.     new->shminfo.readOnly = False;
  806.  
  807.     XShmAttach(display, &(new->shminfo));
  808.     XSync(display, False);
  809.  
  810.     if (gXErrorFlag) {
  811.       /* Ultimate failure here. */
  812.       XDestroyImage(new->ximage);
  813.       new->ximage = NULL;
  814.       shmemFlag = 0;
  815.       gXErrorFlag = 0;
  816.       goto shmemerror;
  817.     } else {
  818.       shmctl(new->shminfo.shmid, IPC_RMID, 0);
  819.     }
  820.  
  821.   } else
  822. #endif
  823.   {
  824. shmemerror:
  825.  
  826.     if (ditherType == FULL_COLOR_DITHER) {
  827.       new->display = (unsigned char *) malloc(width * height * 4);
  828.     } else {
  829.       new->display = (unsigned char *) malloc(width * height);
  830.     }
  831.   }
  832.  
  833.   new->luminance = (unsigned char *) malloc(width * height);
  834.   new->Cr = (unsigned char *) malloc(width * height / 4);
  835.   new->Cb = (unsigned char *) malloc(width * height / 4);
  836.  
  837.   /* Reset locked flag. */
  838.  
  839.   new->locked = 0;
  840.  
  841.   /* Return pointer to new structure. */
  842.  
  843.   return new;
  844. }
  845.  
  846.  
  847.  
  848. /*
  849.  *--------------------------------------------------------------
  850.  *
  851.  * DestroyPictImage --
  852.  *
  853.  *    Deallocates a PictImage structure.
  854.  *
  855.  * Results:
  856.  *      None.
  857.  *
  858.  * Side effects:
  859.  *    None.
  860.  *
  861.  *--------------------------------------------------------------
  862.  */
  863. void
  864. DestroyPictImage(apictimage)
  865.   PictImage *apictimage;
  866. {
  867.   if (apictimage->luminance != NULL) {
  868.     free(apictimage->luminance);
  869.   }
  870.   if (apictimage->Cr != NULL) {
  871.     free(apictimage->Cr);
  872.   }
  873.   if (apictimage->Cb != NULL) {
  874.     free(apictimage->Cb);
  875.   }
  876. #ifdef SH_MEM
  877.   if (apictimage->ximage != NULL) {
  878.     XShmDetach(display, &(apictimage->shminfo));
  879.     XDestroyImage(apictimage->ximage);
  880.     shmdt(apictimage->shminfo.shmaddr);
  881.     apictimage->ximage = NULL;
  882.     apictimage->display = NULL;
  883.   }
  884. #endif
  885.  
  886.   if (apictimage->display != NULL) {
  887.     free(apictimage->display);
  888.   }
  889.   free(apictimage);
  890. }
  891.  
  892.  
  893.  
  894. /*
  895.  *--------------------------------------------------------------
  896.  *
  897.  * mpegVidRsrc --
  898.  *
  899.  *      Parses bit stream until MB_QUANTUM number of
  900.  *      macroblocks have been decoded or current slice or
  901.  *      picture ends, whichever comes first. If the start
  902.  *      of a frame is encountered, the frame is time stamped
  903.  *      with the value passed in time_stamp. If the value
  904.  *      passed in buffer is not null, the video stream buffer
  905.  *      is set to buffer and the length of the buffer is
  906.  *      expected in value passed in through length. The current
  907.  *      video stream is set to vid_stream. If vid_stream
  908.  *      is passed as NULL, a new VidStream structure is created
  909.  *      and initialized and used as the current video stream.
  910.  *
  911.  * Results:
  912.  *      A pointer to the video stream structure used.
  913.  *
  914.  * Side effects:
  915.  *      Bit stream is irreversibly parsed. If a picture is completed,
  916.  *      a function is called to display the frame at the correct time.
  917.  *
  918.  *--------------------------------------------------------------
  919.  */
  920.  
  921. VidStream *
  922. mpegVidRsrc(time_stamp, vid_stream)
  923.   TimeStamp time_stamp;
  924.   VidStream *vid_stream;
  925. {
  926.   static int first = 1;
  927.   unsigned int data;
  928.   int i, status;
  929.  
  930.   /* If vid_stream is null, create new VidStream structure. */
  931.  
  932.   if (vid_stream == NULL) {
  933.     return NULL;
  934.   }
  935.   /*
  936.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  937.    * curVidStream and are not passed vid_stream. Also set global bitstream
  938.    * parameters.
  939.    */
  940.  
  941.   curVidStream = vid_stream;
  942.   bitOffset = curVidStream->bit_offset;
  943. #ifdef UTIL2
  944.   curBits = *curVidStream->buffer << bitOffset;
  945. #else
  946.   curBits = *curVidStream->buffer;
  947. #endif
  948.   bufLength = curVidStream->buf_length;
  949.   bitBuffer = curVidStream->buffer;
  950.  
  951.   /*
  952.    * If called for the first time, find start code, make sure it is a
  953.    * sequence start code.
  954.    */
  955.  
  956.   if (first) {
  957.     next_start_code();
  958.     show_bits32(data);
  959.     if (data != SEQ_START_CODE) {
  960.       fprintf(stderr, "This is not an MPEG stream.");
  961.       DestroyVidStream(curVidStream);
  962.       exit(1);
  963.     }
  964.     first = 0;
  965.   }
  966.   /* Get next 32 bits (size of start codes). */
  967.  
  968.   show_bits32(data);
  969.  
  970.   /*
  971.    * Process according to start code (or parse macroblock if not a start code
  972.    * at all.
  973.    */
  974.  
  975.   switch (data) {
  976.  
  977.   case SEQ_END_CODE:
  978.  
  979.     /* Display last frame. */
  980.  
  981.     if (vid_stream->future != NULL) {
  982.       vid_stream->current = vid_stream->future;
  983.       ExecuteDisplay(vid_stream);
  984.     }
  985.     
  986.     /* Sequence done. Do the right thing. For right now, exit. */
  987.  
  988. #ifdef ANALYSIS
  989.     PrintAllStats();
  990. #endif
  991.     PrintTimeInfo();
  992.  
  993.     if (loopFlag)
  994.       longjmp(env, 1);
  995.  
  996.     DestroyVidStream(curVidStream);
  997.     exit(0);
  998.     break;
  999.  
  1000.   case SEQ_START_CODE:
  1001.  
  1002.     /* Sequence start code. Parse sequence header. */
  1003.  
  1004.     if (ParseSeqHead(vid_stream) != PARSE_OK)
  1005.       goto error;
  1006.  
  1007.     /*
  1008.      * Return after sequence start code so that application above can use
  1009.      * info in header.
  1010.      */
  1011.  
  1012.     goto done;
  1013.  
  1014.   case GOP_START_CODE:
  1015.  
  1016.     /* Group of Pictures start code. Parse gop header. */
  1017.  
  1018.     if (ParseGOP(vid_stream) != PARSE_OK)
  1019.       goto error;
  1020.  
  1021.  
  1022.   case PICTURE_START_CODE:
  1023.  
  1024.     /* Picture start code. Parse picture header and first slice header. */
  1025.  
  1026.     status = ParsePicture(vid_stream, time_stamp);
  1027.  
  1028.     if (status == SKIP_PICTURE) {
  1029.       next_start_code();
  1030. //      fprintf(stderr, "Skipping picture...");
  1031.       while (!next_bits(32, PICTURE_START_CODE)) {
  1032.     if (next_bits(32, GOP_START_CODE))
  1033.       break;
  1034.     else if (next_bits(32, SEQ_END_CODE))
  1035.       break;
  1036.     flush_bits(24);
  1037.     next_start_code();
  1038.       }
  1039. //      fprintf(stderr, "Done.\n");
  1040.       goto done;
  1041.     } else if (status != PARSE_OK)
  1042.       goto error;
  1043.  
  1044.  
  1045.     if (ParseSlice(vid_stream) != PARSE_OK)
  1046.       goto error;
  1047.     break;
  1048.  
  1049.   default:
  1050.  
  1051.     /* Check for slice start code. */
  1052.  
  1053.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  1054.  
  1055.       /* Slice start code. Parse slice header. */
  1056.  
  1057.       if (ParseSlice(vid_stream) != PARSE_OK)
  1058.     goto error;
  1059.     }
  1060.     break;
  1061.   }
  1062.  
  1063.   /* Parse next MB_QUANTUM macroblocks. */
  1064.  
  1065.   for (i = 0; i < MB_QUANTUM; i++) {
  1066.  
  1067.     /* Check to see if actually a startcode and not a macroblock. */
  1068.  
  1069.     if (!next_bits(23, 0x00000000)) {
  1070.  
  1071.       /* Not start code. Parse Macroblock. */
  1072.  
  1073.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  1074.     goto error;
  1075.  
  1076. #ifdef ANALYSIS
  1077.       if (showmb_flag) {
  1078.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  1079.               vid_stream->current->Cb, vid_stream->current->display,
  1080.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  1081.     ExecuteDisplay(vid_stream);
  1082.       }
  1083. #endif
  1084.  
  1085.     } else {
  1086.  
  1087.       /* Not macroblock, actually start code. Get start code. */
  1088.  
  1089.       next_start_code();
  1090.       show_bits32(data);
  1091.  
  1092.       /*
  1093.        * If start code is outside range of slice start codes, frame is
  1094.        * complete, display frame.
  1095.        */
  1096.  
  1097.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  1098.  
  1099. #ifdef ANALYSIS
  1100.     EndTime();
  1101.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  1102.     if (showEachFlag) {
  1103.       PrintOneStat();
  1104.     };
  1105.  
  1106.     CollectStats();
  1107. #endif
  1108.  
  1109.     DoPictureDisplay(vid_stream);
  1110.       }
  1111.       break;
  1112.     }
  1113.   }
  1114.  
  1115.   /* Return pointer to video stream structure. */
  1116.  
  1117.   goto done;
  1118.  
  1119. error:
  1120.   fprintf(stderr, "Error!!!!\n");
  1121.   next_start_code();
  1122.   goto done;
  1123.  
  1124. done:
  1125.  
  1126.   /* Copy global bit i/o variables back into vid_stream. */
  1127.  
  1128.   vid_stream->buffer = bitBuffer;
  1129.   vid_stream->buf_length = bufLength;
  1130.   vid_stream->bit_offset = bitOffset;
  1131.  
  1132.   return vid_stream;
  1133.  
  1134. }
  1135.  
  1136.  
  1137.  
  1138. /*
  1139.  *--------------------------------------------------------------
  1140.  *
  1141.  * ParseSeqHead --
  1142.  *
  1143.  *      Assumes bit stream is at the begining of the sequence
  1144.  *      header start code. Parses off the sequence header.
  1145.  *
  1146.  * Results:
  1147.  *      Fills the vid_stream structure with values derived and
  1148.  *      decoded from the sequence header. Allocates the pict image
  1149.  *      structures based on the dimensions of the image space
  1150.  *      found in the sequence header.
  1151.  *
  1152.  * Side effects:
  1153.  *      Bit stream irreversibly parsed off.
  1154.  *
  1155.  *--------------------------------------------------------------
  1156.  */
  1157.  
  1158. static int
  1159. ParseSeqHead(vid_stream)
  1160.   VidStream *vid_stream;
  1161. {
  1162.  
  1163.   unsigned int data;
  1164.   int i;
  1165.  
  1166.   /* Flush off sequence start code. */
  1167.  
  1168.   flush_bits32;
  1169.  
  1170.   /* Get horizontal size of image space. */
  1171.  
  1172.   get_bits12(data);
  1173.   vid_stream->h_size = data;
  1174.  
  1175.   /* Get vertical size of image space. */
  1176.  
  1177.   get_bits12(data);
  1178.   vid_stream->v_size = data;
  1179.  
  1180.   /* Calculate macroblock width and height of image space. */
  1181.  
  1182.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  1183.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  1184.  
  1185.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  1186.  
  1187.   lmaxx = vid_stream->mb_width*16-1;
  1188.   lmaxy = vid_stream->mb_height*16-1;
  1189.   cmaxx = vid_stream->mb_width*8-1;
  1190.   cmaxy = vid_stream->mb_height*8-1;
  1191.  
  1192.   /*
  1193.    * Initialize ring buffer of pict images now that dimensions of image space
  1194.    * are known.
  1195.    */
  1196.  
  1197. #ifdef SH_MEM
  1198.   if (display != NULL) {
  1199.     InstallXErrorHandler();
  1200.   }
  1201. #endif
  1202.  
  1203.   if (vid_stream->ring[0] == NULL) {
  1204.     for (i = 0; i < RING_BUF_SIZE; i++) {
  1205.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  1206.                      vid_stream->mb_height * 16);
  1207.     }
  1208.   }
  1209. #ifdef SH_MEM
  1210.   if (display != NULL) {
  1211.     DeInstallXErrorHandler();
  1212.   }
  1213. #endif
  1214.  
  1215.   /* Parse of aspect ratio code. */
  1216.  
  1217.   get_bits4(data);
  1218.   vid_stream->aspect_ratio = (unsigned char) data;
  1219.  
  1220.   /* Parse off picture rate code. */
  1221.  
  1222.   get_bits4(data);
  1223.   vid_stream->picture_rate = (unsigned char) data;
  1224.  
  1225.   /* Parse off bit rate. */
  1226.  
  1227.   get_bits18(data);
  1228.   vid_stream->bit_rate = data;
  1229.  
  1230.   /* Flush marker bit. */
  1231.  
  1232.   flush_bits(1);
  1233.  
  1234.   /* Parse off vbv buffer size. */
  1235.  
  1236.   get_bits10(data);
  1237.   vid_stream->vbv_buffer_size = data;
  1238.  
  1239.   /* Parse off contrained parameter flag. */
  1240.  
  1241.   get_bits1(data);
  1242.   if (data) {
  1243.     vid_stream->const_param_flag = TRUE;
  1244.   } else
  1245.     vid_stream->const_param_flag = FALSE;
  1246.  
  1247.   /*
  1248.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  1249.    */
  1250.  
  1251.   get_bits1(data);
  1252.   if (data) {
  1253.     for (i = 0; i < 64; i++) {
  1254.       get_bits8(data);
  1255.  
  1256.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1257.     (unsigned char) data;
  1258.     }
  1259.   }
  1260.   /*
  1261.    * If non intra quant matrix flag set, parse off non intra quant matrix
  1262.    * values.
  1263.    */
  1264.  
  1265.   get_bits1(data);
  1266.   if (data) {
  1267.     for (i = 0; i < 64; i++) {
  1268.       get_bits8(data);
  1269.  
  1270.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1271.     (unsigned char) data;
  1272.     }
  1273.   }
  1274.   /* Go to next start code. */
  1275.  
  1276.   next_start_code();
  1277.  
  1278.   /*
  1279.    * If next start code is extension start code, parse off extension data.
  1280.    */
  1281.  
  1282.   if (next_bits(32, EXT_START_CODE)) {
  1283.     flush_bits32;
  1284.     if (vid_stream->ext_data != NULL) {
  1285.       free(vid_stream->ext_data);
  1286.       vid_stream->ext_data = NULL;
  1287.     }
  1288.     vid_stream->ext_data = get_ext_data();
  1289.   }
  1290.   /* If next start code is user start code, parse off user data. */
  1291.  
  1292.   if (next_bits(32, USER_START_CODE)) {
  1293.     flush_bits32;
  1294.     if (vid_stream->user_data != NULL) {
  1295.       free(vid_stream->user_data);
  1296.       vid_stream->user_data = NULL;
  1297.     }
  1298.     vid_stream->user_data = get_ext_data();
  1299.   }
  1300.   return PARSE_OK;
  1301. }
  1302.  
  1303.  
  1304.  
  1305. /*
  1306.  *--------------------------------------------------------------
  1307.  *
  1308.  * ParseGOP --
  1309.  *
  1310.  *      Parses of group of pictures header from bit stream
  1311.  *      associated with vid_stream.
  1312.  *
  1313.  * Results:
  1314.  *      Values in gop header placed into video stream structure.
  1315.  *
  1316.  * Side effects:
  1317.  *      Bit stream irreversibly parsed.
  1318.  *
  1319.  *--------------------------------------------------------------
  1320.  */
  1321.  
  1322. static int
  1323. ParseGOP(vid_stream)
  1324.   VidStream *vid_stream;
  1325. {
  1326.   unsigned int data;
  1327.  
  1328.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  1329.  
  1330.   flush_bits32;
  1331.  
  1332.   /* Parse off drop frame flag. */
  1333.  
  1334.   get_bits1(data);
  1335.   if (data) {
  1336.     vid_stream->group.drop_flag = TRUE;
  1337.   } else
  1338.     vid_stream->group.drop_flag = FALSE;
  1339.  
  1340.   /* Parse off hour component of time code. */
  1341.  
  1342.   get_bits5(data);
  1343.   vid_stream->group.tc_hours = data;
  1344.  
  1345.   /* Parse off minute component of time code. */
  1346.  
  1347.   get_bits6(data);
  1348.   vid_stream->group.tc_minutes = data;
  1349.  
  1350.   /* Flush marker bit. */
  1351.  
  1352.   flush_bits(1);
  1353.  
  1354.   /* Parse off second component of time code. */
  1355.  
  1356.   get_bits6(data);
  1357.   vid_stream->group.tc_seconds = data;
  1358.  
  1359.   /* Parse off picture count component of time code. */
  1360.  
  1361.   get_bits6(data);
  1362.   vid_stream->group.tc_pictures = data;
  1363.  
  1364.   /* Parse off closed gop and broken link flags. */
  1365.  
  1366.   get_bits2(data);
  1367.   if (data > 1) {
  1368.     vid_stream->group.closed_gop = TRUE;
  1369.     if (data > 2) {
  1370.       vid_stream->group.broken_link = TRUE;
  1371.     } else
  1372.       vid_stream->group.broken_link = FALSE;
  1373.   } else {
  1374.     vid_stream->group.closed_gop = FALSE;
  1375.     if (data) {
  1376.       vid_stream->group.broken_link = TRUE;
  1377.     } else
  1378.       vid_stream->group.broken_link = FALSE;
  1379.   }
  1380.  
  1381.   /* Goto next start code. */
  1382.  
  1383.   next_start_code();
  1384.  
  1385.   /* If next start code is extension data, parse off extension data. */
  1386.  
  1387.   if (next_bits(32, EXT_START_CODE)) {
  1388.     flush_bits32;
  1389.     if (vid_stream->group.ext_data != NULL) {
  1390.       free(vid_stream->group.ext_data);
  1391.       vid_stream->group.ext_data = NULL;
  1392.     }
  1393.     vid_stream->group.ext_data = get_ext_data();
  1394.   }
  1395.   /* If next start code is user data, parse off user data. */
  1396.  
  1397.   if (next_bits(32, USER_START_CODE)) {
  1398.     flush_bits32;
  1399.     if (vid_stream->group.user_data != NULL) {
  1400.       free(vid_stream->group.user_data);
  1401.       vid_stream->group.user_data = NULL;
  1402.     }
  1403.     vid_stream->group.user_data = get_ext_data();
  1404.   }
  1405.   return PARSE_OK;
  1406. }
  1407.  
  1408.  
  1409.  
  1410. /*
  1411.  *--------------------------------------------------------------
  1412.  *
  1413.  * ParsePicture --
  1414.  *
  1415.  *      Parses picture header. Marks picture to be presented
  1416.  *      at particular time given a time stamp.
  1417.  *
  1418.  * Results:
  1419.  *      Values from picture header put into video stream structure.
  1420.  *
  1421.  * Side effects:
  1422.  *      Bit stream irreversibly parsed.
  1423.  *
  1424.  *--------------------------------------------------------------
  1425.  */
  1426.  
  1427. static int
  1428. ParsePicture(vid_stream, time_stamp)
  1429.   VidStream *vid_stream;
  1430.   TimeStamp time_stamp;
  1431. {
  1432.   unsigned int data;
  1433.   int i;
  1434.  
  1435.   /* Flush header start code. */
  1436.   flush_bits32;
  1437.  
  1438.   /* Parse off temporal reference. */
  1439.   get_bits10(data);
  1440.   vid_stream->picture.temp_ref = data;
  1441.  
  1442.   /* Parse of picture type. */
  1443.   get_bits3(data);
  1444.   vid_stream->picture.code_type = data;
  1445.  
  1446.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1447.       (No_B_Flag ||
  1448.        (vid_stream->past == NULL) ||
  1449.        (vid_stream->future == NULL)))
  1450.     return SKIP_PICTURE;
  1451.  
  1452.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1453.       (No_P_Flag || (vid_stream->future == NULL)))
  1454.     return SKIP_PICTURE;
  1455.  
  1456. #ifdef ANALYSIS
  1457.   StartTime();
  1458.   stat_a[0].frametype = vid_stream->picture.code_type;
  1459.   stat_a[0].number = 1;
  1460.   stat_a[0].totsize = 45;
  1461.   pictureSizeCount = bitCountRead();
  1462. #endif
  1463.  
  1464.   /* Parse off vbv buffer delay value. */
  1465.   get_bits16(data);
  1466.   vid_stream->picture.vbv_delay = data;
  1467.  
  1468.   /* If P or B type frame... */
  1469.  
  1470.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  1471.  
  1472.     /* Parse off forward vector full pixel flag. */
  1473.     get_bits1(data);
  1474.     if (data)
  1475.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1476.     else
  1477.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1478.  
  1479.     /* Parse of forw_r_code. */
  1480.     get_bits3(data);
  1481.  
  1482.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1483.  
  1484.     vid_stream->picture.forw_r_size = data - 1;
  1485.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1486.   }
  1487.   /* If B type frame... */
  1488.  
  1489.   if (vid_stream->picture.code_type == 3) {
  1490.  
  1491.     /* Parse off back vector full pixel flag. */
  1492.     get_bits1(data);
  1493.     if (data)
  1494.       vid_stream->picture.full_pel_back_vector = TRUE;
  1495.     else
  1496.       vid_stream->picture.full_pel_back_vector = FALSE;
  1497.  
  1498.     /* Parse off back_r_code. */
  1499.     get_bits3(data);
  1500.  
  1501.     /* Decode back_r_code into back_r_size and back_f. */
  1502.  
  1503.     vid_stream->picture.back_r_size = data - 1;
  1504.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1505.   }
  1506.   /* Get extra bit picture info. */
  1507.  
  1508.   if (vid_stream->picture.extra_info != NULL) {
  1509.     free(vid_stream->picture.extra_info);
  1510.     vid_stream->picture.extra_info = NULL;
  1511.   }
  1512.   vid_stream->picture.extra_info = get_extra_bit_info();
  1513.  
  1514.   /* Goto next start code. */
  1515.   next_start_code();
  1516.  
  1517.   /* If start code is extension start code, parse off extension data. */
  1518.  
  1519.   if (next_bits(32, EXT_START_CODE)) {
  1520.     flush_bits32;
  1521.  
  1522.     if (vid_stream->picture.ext_data != NULL) {
  1523.       free(vid_stream->picture.ext_data);
  1524.       vid_stream->picture.ext_data = NULL;
  1525.     }
  1526.     vid_stream->picture.ext_data = get_ext_data();
  1527.   }
  1528.   /* If start code is user start code, parse off user data. */
  1529.  
  1530.   if (next_bits(32, USER_START_CODE)) {
  1531.     flush_bits32;
  1532.  
  1533.     if (vid_stream->picture.user_data != NULL) {
  1534.       free(vid_stream->picture.user_data);
  1535.       vid_stream->picture.user_data = NULL;
  1536.     }
  1537.     vid_stream->picture.user_data = get_ext_data();
  1538.   }
  1539.   /* Find a pict image structure in ring buffer not currently locked. */
  1540.  
  1541.   i = 0;
  1542.  
  1543.   while (vid_stream->ring[i]->locked != 0) {
  1544.     if (++i >= RING_BUF_SIZE) {
  1545.       perror("Fatal error. Ring buffer full.");
  1546.       exit(1);
  1547.     }
  1548.   }
  1549.  
  1550.   /* Set current pict image structure to the one just found in ring. */
  1551.  
  1552.   vid_stream->current = vid_stream->ring[i];
  1553.  
  1554.   /* Set time stamp. */
  1555.  
  1556.   vid_stream->current->show_time = time_stamp;
  1557.  
  1558.   /* Reset past macroblock address field. */
  1559.  
  1560.   vid_stream->mblock.past_mb_addr = -1;
  1561.  
  1562.   return PARSE_OK;
  1563. }
  1564.  
  1565.  
  1566.  
  1567. /*
  1568.  *--------------------------------------------------------------
  1569.  *
  1570.  * ParseSlice --
  1571.  *
  1572.  *      Parses off slice header.
  1573.  *
  1574.  * Results:
  1575.  *      Values found in slice header put into video stream structure.
  1576.  *
  1577.  * Side effects:
  1578.  *      Bit stream irreversibly parsed.
  1579.  *
  1580.  *--------------------------------------------------------------
  1581.  */
  1582.  
  1583. static int
  1584. ParseSlice(vid_stream)
  1585.   VidStream *vid_stream;
  1586. {
  1587.   unsigned int data;
  1588.  
  1589.   /* Flush slice start code. */
  1590.  
  1591.   flush_bits(24);
  1592.  
  1593.   /* Parse off slice vertical position. */
  1594.  
  1595.   get_bits8(data);
  1596.   vid_stream->slice.vert_pos = data;
  1597.  
  1598.   /* Parse off quantization scale. */
  1599.  
  1600.   get_bits5(data);
  1601.   vid_stream->slice.quant_scale = data;
  1602.  
  1603.   /* Parse off extra bit slice info. */
  1604.  
  1605.   if (vid_stream->slice.extra_info != NULL) {
  1606.     free(vid_stream->slice.extra_info);
  1607.     vid_stream->slice.extra_info = NULL;
  1608.   }
  1609.   vid_stream->slice.extra_info = get_extra_bit_info();
  1610.  
  1611.   /* Reset past intrablock address. */
  1612.  
  1613.   vid_stream->mblock.past_intra_addr = -2;
  1614.  
  1615.   /* Reset previous recon motion vectors. */
  1616.  
  1617.   vid_stream->mblock.recon_right_for_prev = 0;
  1618.   vid_stream->mblock.recon_down_for_prev = 0;
  1619.   vid_stream->mblock.recon_right_back_prev = 0;
  1620.   vid_stream->mblock.recon_down_back_prev = 0;
  1621.  
  1622.   /* Reset macroblock address. */
  1623.  
  1624.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1625.                    vid_stream->mb_width) - 1;
  1626.  
  1627.   /* Reset past dct dc y, cr, and cb values. */
  1628.  
  1629.   vid_stream->block.dct_dc_y_past = 1024;
  1630.   vid_stream->block.dct_dc_cr_past = 1024;
  1631.   vid_stream->block.dct_dc_cb_past = 1024;
  1632.  
  1633.   return PARSE_OK;
  1634. }
  1635.  
  1636.  
  1637.  
  1638. /*
  1639.  *--------------------------------------------------------------
  1640.  *
  1641.  * ParseMacroBlock --
  1642.  *
  1643.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1644.  *      inverse DCT, reconstructs motion vectors, calculates and
  1645.  *      set pixel values for macroblock in current pict image
  1646.  *      structure.
  1647.  *
  1648.  * Results:
  1649.  *      Here's where everything really happens. Welcome to the
  1650.  *      heart of darkness.
  1651.  *
  1652.  * Side effects:
  1653.  *      Bit stream irreversibly parsed off.
  1654.  *
  1655.  *--------------------------------------------------------------
  1656.  */
  1657.  
  1658. static int
  1659. ParseMacroBlock(vid_stream)
  1660.   VidStream *vid_stream;
  1661. {
  1662.   int addr_incr;
  1663.   unsigned int data;
  1664.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1665.       recon_down_back;
  1666.   int zero_block_flag;
  1667.   BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern;
  1668.   int no_dith_flag = 0;
  1669.  
  1670. #ifdef ANALYSIS
  1671.   mbSizeCount = bitCountRead();
  1672. #endif
  1673.  
  1674.   /*
  1675.    * Parse off macroblock address increment and add to macroblock address.
  1676.    */
  1677.   do {
  1678.     DecodeMBAddrInc(addr_incr);
  1679.     if (addr_incr == MB_ESCAPE) {
  1680.       vid_stream->mblock.mb_address += 33;
  1681.       addr_incr = MB_STUFFING;
  1682.     }
  1683.   } while (addr_incr == MB_STUFFING);
  1684.   vid_stream->mblock.mb_address += addr_incr;
  1685.  
  1686.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1687.                        vid_stream->mb_width - 1))
  1688.     return SKIP_TO_START_CODE;
  1689.  
  1690.   /*
  1691.    * If macroblocks have been skipped, process skipped macroblocks.
  1692.    */
  1693.  
  1694.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1695.     if (vid_stream->picture.code_type == P_TYPE)
  1696.       ProcessSkippedPFrameMBlocks(vid_stream);
  1697.     else if (vid_stream->picture.code_type == B_TYPE)
  1698.       ProcessSkippedBFrameMBlocks(vid_stream);
  1699.   }
  1700.   /* Set past macroblock address to current macroblock address. */
  1701.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1702.  
  1703.   /* Based on picture type decode macroblock type. */
  1704.   switch (vid_stream->picture.code_type) {
  1705.   case I_TYPE:
  1706.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1707.           vid_stream->mblock.mb_intra);
  1708.     break;
  1709.  
  1710.   case P_TYPE:
  1711.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1712.           vid_stream->mblock.mb_intra);
  1713.     break;
  1714.  
  1715.   case B_TYPE:
  1716.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1717.           vid_stream->mblock.mb_intra);
  1718.     break;
  1719.   }
  1720.  
  1721.   /* If quantization flag set, parse off new quantization scale. */
  1722.  
  1723.   if (mb_quant == TRUE) {
  1724.     get_bits5(data);
  1725.     vid_stream->slice.quant_scale = data;
  1726.   }
  1727.   /* If forward motion vectors exist... */
  1728.   if (mb_motion_forw == TRUE) {
  1729.  
  1730.     /* Parse off and decode horizontal forward motion vector. */
  1731.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1732.  
  1733.     /* If horiz. forward r data exists, parse off. */
  1734.  
  1735.     if ((vid_stream->picture.forw_f != 1) &&
  1736.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1737.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1738.       vid_stream->mblock.motion_h_forw_r = data;
  1739.     }
  1740.     /* Parse off and decode vertical forward motion vector. */
  1741.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1742.  
  1743.     /* If vert. forw. r data exists, parse off. */
  1744.  
  1745.     if ((vid_stream->picture.forw_f != 1) &&
  1746.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1747.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1748.       vid_stream->mblock.motion_v_forw_r = data;
  1749.     }
  1750.   }
  1751.   /* If back motion vectors exist... */
  1752.   if (mb_motion_back == TRUE) {
  1753.  
  1754.     /* Parse off and decode horiz. back motion vector. */
  1755.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1756.  
  1757.     /* If horiz. back r data exists, parse off. */
  1758.  
  1759.     if ((vid_stream->picture.back_f != 1) &&
  1760.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1761.       get_bitsn(vid_stream->picture.back_r_size, data);
  1762.       vid_stream->mblock.motion_h_back_r = data;
  1763.     }
  1764.     /* Parse off and decode vert. back motion vector. */
  1765.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1766.  
  1767.     /* If vert. back r data exists, parse off. */
  1768.  
  1769.     if ((vid_stream->picture.back_f != 1) &&
  1770.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1771.       get_bitsn(vid_stream->picture.back_r_size, data);
  1772.       vid_stream->mblock.motion_v_back_r = data;
  1773.     }
  1774.   }
  1775. #ifdef ANALYSIS
  1776.   if (vid_stream->mblock.mb_intra) {
  1777.     stat_a[0].i_mbnum++;
  1778.     mbCBPPtr = stat_a[0].i_mbcbp;
  1779.     mbCoeffPtr = stat_a[0].i_mbcoeff;
  1780.     mbSizePtr = &(stat_a[0].i_mbsize);
  1781.   } else if (mb_motion_back && mb_motion_forw) {
  1782.     stat_a[0].bi_mbnum++;
  1783.     mbCBPPtr = stat_a[0].bi_mbcbp;
  1784.     mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1785.     mbSizePtr = &(stat_a[0].bi_mbsize);
  1786.   } else if (mb_motion_back) {
  1787.     stat_a[0].b_mbnum++;
  1788.     mbCBPPtr = stat_a[0].b_mbcbp;
  1789.     mbCoeffPtr = stat_a[0].b_mbcoeff;
  1790.     mbSizePtr = &(stat_a[0].b_mbsize);
  1791.   } else {
  1792.     stat_a[0].p_mbnum++;
  1793.     mbCBPPtr = stat_a[0].p_mbcbp;
  1794.     mbCoeffPtr = stat_a[0].p_mbcoeff;
  1795.     mbSizePtr = &(stat_a[0].p_mbsize);
  1796.   }
  1797. #endif
  1798.  
  1799.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1800.   if (mb_pattern == TRUE) {
  1801.     DecodeCBP(vid_stream->mblock.cbp);
  1802.   }
  1803.   /* Otherwise, set CBP to zero. */
  1804.   else
  1805.     vid_stream->mblock.cbp = 0;
  1806.  
  1807.  
  1808. #ifdef ANALYSIS
  1809.   mbCBPPtr[vid_stream->mblock.cbp]++;
  1810. #endif
  1811.  
  1812.   /* Reconstruct motion vectors depending on picture type. */
  1813.   if (vid_stream->picture.code_type == P_TYPE) {
  1814.  
  1815.     /*
  1816.      * If no forw motion vectors, reset previous and current vectors to 0.
  1817.      */
  1818.  
  1819.     if (!mb_motion_forw) {
  1820.       recon_right_for = 0;
  1821.       recon_down_for = 0;
  1822.       vid_stream->mblock.recon_right_for_prev = 0;
  1823.       vid_stream->mblock.recon_down_for_prev = 0;
  1824.     }
  1825.     /*
  1826.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1827.      * current vectors.
  1828.      */
  1829.  
  1830.     else {
  1831.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1832.     }
  1833.   }
  1834.   if (vid_stream->picture.code_type == B_TYPE) {
  1835.  
  1836.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1837.  
  1838.     if (vid_stream->mblock.mb_intra) {
  1839.       vid_stream->mblock.recon_right_for_prev = 0;
  1840.       vid_stream->mblock.recon_down_for_prev = 0;
  1841.       vid_stream->mblock.recon_right_back_prev = 0;
  1842.       vid_stream->mblock.recon_down_back_prev = 0;
  1843.     } else {
  1844.  
  1845.       /* If no forw vectors, current vectors equal prev. vectors. */
  1846.  
  1847.       if (!mb_motion_forw) {
  1848.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1849.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1850.       }
  1851.       /*
  1852.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1853.        */
  1854.  
  1855.       else {
  1856.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1857.       }
  1858.  
  1859.       /* If no back vectors, set back vectors to prev back vectors. */
  1860.  
  1861.       if (!mb_motion_back) {
  1862.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1863.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1864.       }
  1865.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1866.  
  1867.       else {
  1868.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1869.       }
  1870.  
  1871.       /*
  1872.        * Store vector existance flags in structure for possible skipped
  1873.        * macroblocks to follow.
  1874.        */
  1875.  
  1876.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  1877.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  1878.     }
  1879.   }
  1880.  
  1881.   /* For each possible block in macroblock. */
  1882.   if (ditherType == GRAY_DITHER ||
  1883.       ditherType == MONO_DITHER ||
  1884.       ditherType == MONO_THRESHOLD) {
  1885.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  1886.  
  1887.       /* If block exists... */
  1888.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1889.     zero_block_flag = 0;
  1890.     ParseReconBlock(i);
  1891.       } else {
  1892.     zero_block_flag = 1;
  1893.       }
  1894.  
  1895.       /* If macroblock is intra coded... */
  1896.       if (vid_stream->mblock.mb_intra) {
  1897.     ReconIMBlock(vid_stream, i);
  1898.       } else if (mb_motion_forw && mb_motion_back) {
  1899.     ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1900.               recon_right_back, recon_down_back, zero_block_flag);
  1901.       } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1902.     ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1903.              zero_block_flag);
  1904.       } else if (mb_motion_back) {
  1905.     ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1906.              zero_block_flag);
  1907.       }
  1908.     }
  1909.     /* Kill the Chrominace blocks... */
  1910.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) {
  1911.         ParseAwayBlock(4);
  1912.     }
  1913.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) {
  1914.         ParseAwayBlock(5);
  1915.     }
  1916.   } else {
  1917.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1918.     
  1919.     /* If block exists... */
  1920.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1921.       zero_block_flag = 0;
  1922.       ParseReconBlock(i);
  1923.     } else {
  1924.       zero_block_flag = 1;
  1925.     }
  1926.     
  1927.     /* If macroblock is intra coded... */
  1928.     if (vid_stream->mblock.mb_intra) {
  1929.       ReconIMBlock(vid_stream, i);
  1930.     } else if (mb_motion_forw && mb_motion_back) {
  1931.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1932.             recon_right_back, recon_down_back, zero_block_flag);
  1933.     } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1934.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1935.                zero_block_flag);
  1936.     } else if (mb_motion_back) {
  1937.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1938.                zero_block_flag);
  1939.     }
  1940.       }
  1941.   }
  1942.  
  1943.   /* If D Type picture, flush marker bit. */
  1944.   if (vid_stream->picture.code_type == 4)
  1945.     flush_bits(1);
  1946.  
  1947.   /* If macroblock was intracoded, set macroblock past intra address. */
  1948.   if (vid_stream->mblock.mb_intra)
  1949.     vid_stream->mblock.past_intra_addr =
  1950.       vid_stream->mblock.mb_address;
  1951.  
  1952. #ifdef ANALYSIS
  1953.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1954. #endif
  1955.   return PARSE_OK;
  1956. }
  1957.  
  1958.  
  1959.  
  1960. /*
  1961.  *--------------------------------------------------------------
  1962.  *
  1963.  * ReconIMBlock --
  1964.  *
  1965.  *    Reconstructs intra coded macroblock.
  1966.  *
  1967.  * Results:
  1968.  *    None.
  1969.  *
  1970.  * Side effects:
  1971.  *    None.
  1972.  *
  1973.  *--------------------------------------------------------------
  1974.  */
  1975.  
  1976. static void
  1977. ReconIMBlock(vid_stream, bnum)
  1978.   VidStream *vid_stream;
  1979.   int bnum;
  1980. {
  1981.   int mb_row, mb_col, row, col, row_size, rr;
  1982.   unsigned char *dest;
  1983.  
  1984.   /* Calculate macroblock row and column from address. */
  1985.  
  1986.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  1987.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  1988.  
  1989.  
  1990.   /* If block is luminance block... */
  1991.  
  1992.   if (bnum < 4) {
  1993.  
  1994.     /* Calculate row and col values for upper left pixel of block. */
  1995.  
  1996.     row = mb_row * 16;
  1997.     col = mb_col * 16;
  1998.     if (bnum > 1)
  1999.       row += 8;
  2000.     if (bnum % 2)
  2001.       col += 8;
  2002.  
  2003.     /* Set dest to luminance plane of current pict image. */
  2004.  
  2005.     dest = vid_stream->current->luminance;
  2006.  
  2007.     /* Establish row size. */
  2008.  
  2009.     row_size = vid_stream->mb_width * 16;
  2010.   }
  2011.   /* Otherwise if block is Cr block... */
  2012.  
  2013.   else if (bnum == 4) {
  2014.  
  2015.     /* Set dest to Cr plane of current pict image. */
  2016.  
  2017.     dest = vid_stream->current->Cr;
  2018.  
  2019.     /* Establish row size. */
  2020.  
  2021.     row_size = vid_stream->mb_width * 8;
  2022.  
  2023.     /* Calculate row,col for upper left pixel of block. */
  2024.  
  2025.     row = mb_row * 8;
  2026.     col = mb_col * 8;
  2027.   }
  2028.   /* Otherwise block is Cb block, and ... */
  2029.  
  2030.   else {
  2031.  
  2032.     /* Set dest to Cb plane of current pict image. */
  2033.  
  2034.     dest = vid_stream->current->Cb;
  2035.  
  2036.     /* Establish row size. */
  2037.  
  2038.     row_size = vid_stream->mb_width * 8;
  2039.  
  2040.     /* Calculate row,col for upper left pixel value of block. */
  2041.  
  2042.     row = mb_row * 8;
  2043.     col = mb_col * 8;
  2044.   }
  2045.  
  2046.   /*
  2047.    * For each pixel in block, set to cropped reconstructed value from inverse
  2048.    * dct.
  2049.    */
  2050.   {
  2051.     short *sp = &vid_stream->block.dct_recon[0][0];
  2052.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2053.     dest += row * row_size + col;
  2054.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  2055.       dest[0] = cm[sp[0]];
  2056.       assertCrop(sp[0]);
  2057.       dest[1] = cm[sp[1]];
  2058.       assertCrop(sp[1]);
  2059.       dest[2] = cm[sp[2]];
  2060.       assertCrop(sp[2]);
  2061.       dest[3] = cm[sp[3]];
  2062.       assertCrop(sp[3]);
  2063.       dest[4] = cm[sp[4]];
  2064.       assertCrop(sp[4]);
  2065.       dest[5] = cm[sp[5]];
  2066.       assertCrop(sp[5]);
  2067.       dest[6] = cm[sp[6]];
  2068.       assertCrop(sp[6]);
  2069.       dest[7] = cm[sp[7]];
  2070.       assertCrop(sp[7]);
  2071.  
  2072.       dest += row_size;
  2073.       dest[0] = cm[sp[8]];
  2074.       assertCrop(sp[8]);
  2075.       dest[1] = cm[sp[9]];
  2076.       assertCrop(sp[9]);
  2077.       dest[2] = cm[sp[10]];
  2078.       assertCrop(sp[10]);
  2079.       dest[3] = cm[sp[11]];
  2080.       assertCrop(sp[11]);
  2081.       dest[4] = cm[sp[12]];
  2082.       assertCrop(sp[12]);
  2083.       dest[5] = cm[sp[13]];
  2084.       assertCrop(sp[13]);
  2085.       dest[6] = cm[sp[14]];
  2086.       assertCrop(sp[14]);
  2087.       dest[7] = cm[sp[15]];
  2088.       assertCrop(sp[15]);
  2089.     }
  2090.   }
  2091. }
  2092.  
  2093.  
  2094.  
  2095. /*
  2096.  *--------------------------------------------------------------
  2097.  *
  2098.  * ReconPMBlock --
  2099.  *
  2100.  *    Reconstructs forward predicted macroblocks.
  2101.  *
  2102.  * Results:
  2103.  *      None.
  2104.  *
  2105.  * Side effects:
  2106.  *      None.
  2107.  *
  2108.  *--------------------------------------------------------------
  2109.  */
  2110.  
  2111. static void
  2112. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  2113.   VidStream *vid_stream;
  2114.   int bnum, recon_right_for, recon_down_for, zflag;
  2115. {
  2116.   int mb_row, mb_col, row, col, row_size, rr;
  2117.   unsigned char *dest, *past;
  2118.   static int right_for, down_for, right_half_for, down_half_for;
  2119.   unsigned char *rindex1, *rindex2;
  2120.   unsigned char *index;
  2121.   short int *blockvals;
  2122.  
  2123. #ifdef LOOSE_MPEG
  2124.   int maxx, maxy;
  2125.   int illegalBlock = 0;
  2126.   int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
  2127. #endif
  2128.  
  2129.   /* Calculate macroblock row and column from address. */
  2130.  
  2131.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2132.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2133.  
  2134.   if (bnum < 4) {
  2135.  
  2136.     /* Calculate right_for, down_for motion vectors. */
  2137.  
  2138.     right_for = recon_right_for >> 1;
  2139.     down_for = recon_down_for >> 1;
  2140.     right_half_for = recon_right_for & 0x1;
  2141.     down_half_for = recon_down_for & 0x1;
  2142.  
  2143.     /* Set dest to luminance plane of current pict image. */
  2144.  
  2145.     dest = vid_stream->current->luminance;
  2146.  
  2147.     if (vid_stream->picture.code_type == B_TYPE) {
  2148.       if (vid_stream->past != NULL)
  2149.     past = vid_stream->past->luminance;
  2150.     } else {
  2151.  
  2152.       /* Set predicitive frame to current future frame. */
  2153.  
  2154.       if (vid_stream->future != NULL)
  2155.     past = vid_stream->future->luminance;
  2156.     }
  2157.  
  2158.     /* Establish row size. */
  2159.  
  2160.     row_size = vid_stream->mb_width << 4;
  2161.  
  2162.     /* Calculate row,col of upper left pixel in block. */
  2163.  
  2164.     row = mb_row << 4;
  2165.     col = mb_col << 4;
  2166.     if (bnum > 1)
  2167.       row += 8;
  2168.     if (bnum % 2)
  2169.       col += 8;
  2170.  
  2171. #ifdef LOOSE_MPEG
  2172.     /* Check for block illegality. */
  2173.  
  2174.     maxx = lmaxx; maxy = lmaxy;
  2175.  
  2176.     if (row + down_for + 7 > maxy) illegalBlock |= 0x4;
  2177.     else if (row + down_for < 0)  illegalBlock |= 0x1;
  2178.     
  2179.     if (col + right_for + 7 > maxx) illegalBlock |= 0x2;
  2180.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2181.  
  2182. #endif
  2183.   }
  2184.   /* Otherwise, block is NOT luminance block, ... */
  2185.  
  2186.   else {
  2187.  
  2188.     /* Construct motion vectors. */
  2189.  
  2190.     recon_right_for /= 2;
  2191.     recon_down_for /= 2;
  2192.     right_for = recon_right_for >> 1;
  2193.     down_for = recon_down_for >> 1;
  2194.     right_half_for = recon_right_for & 0x1;
  2195.     down_half_for = recon_down_for & 0x1;
  2196.  
  2197.     /* Establish row size. */
  2198.  
  2199.     row_size = vid_stream->mb_width << 3;
  2200.  
  2201.     /* Calculate row,col of upper left pixel in block. */
  2202.  
  2203.     row = mb_row << 3;
  2204.     col = mb_col << 3;
  2205.  
  2206. #ifdef LOOSE_MPEG
  2207.     /* Check for block illegality. */
  2208.  
  2209.     maxx = cmaxx; maxy = cmaxy;
  2210.  
  2211.     if (row + down_for  + 7 > maxy) illegalBlock |= 0x4;
  2212.     else if (row + down_for < 0) illegalBlock |= 0x1;
  2213.  
  2214.     if (col + right_for  + 7 > maxx) illegalBlock  |= 0x2;
  2215.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2216.  
  2217. #endif
  2218.  
  2219.     /* If block is Cr block... */
  2220.  
  2221.     if (bnum == 4) {
  2222.  
  2223.       /* Set dest to Cr plane of current pict image. */
  2224.  
  2225.       dest = vid_stream->current->Cr;
  2226.  
  2227.       if (vid_stream->picture.code_type == B_TYPE) {
  2228.  
  2229.     if (vid_stream->past != NULL)
  2230.       past = vid_stream->past->Cr;
  2231.       } else {
  2232.     if (vid_stream->future != NULL)
  2233.       past = vid_stream->future->Cr;
  2234.       }
  2235.     }
  2236.     /* Otherwise, block is Cb block... */
  2237.  
  2238.     else {
  2239.  
  2240.       /* Set dest to Cb plane of current pict image. */
  2241.  
  2242.       dest = vid_stream->current->Cb;
  2243.  
  2244.       if (vid_stream->picture.code_type == B_TYPE) {
  2245.     if (vid_stream->past != NULL)
  2246.       past = vid_stream->past->Cb;
  2247.       } else {
  2248.     if (vid_stream->future != NULL)
  2249.       past = vid_stream->future->Cb;
  2250.       }
  2251.     }
  2252.   }
  2253.  
  2254.   /* For each pixel in block... */
  2255.  
  2256. #ifdef LOOSE_MPEG
  2257.  
  2258.   if (illegalBlock) {
  2259.     if (illegalBlock & 0x1) {
  2260.       row_start = 0;
  2261.       row_end = row+down_for+8;
  2262.       rfirst = rlast = 8 - row_end;
  2263.     }
  2264.     else if (illegalBlock & 0x4) {
  2265.       row_start = row + down_for;
  2266.       row_end = maxy+1;
  2267.       rlast = row_end - row_start - 1;
  2268.       rfirst = 0;
  2269.     }
  2270.     else {
  2271.       row_start = row+down_for;
  2272.       row_end = row_start+8;
  2273.       rfirst = 0;
  2274.     }
  2275.  
  2276.     if (illegalBlock & 0x8) {
  2277.       col_start = 0;
  2278.       col_end = col + right_for + 8;
  2279.       cfirst = clast = 8 - col_end;
  2280.     }
  2281.     else if (illegalBlock & 0x2) {
  2282.       col_start = col + right_for;
  2283.       col_end = maxx + 1;
  2284.       clast = col_end - col_start - 1;
  2285.       cfirst = 0;
  2286.     }
  2287.     else {
  2288.       col_start = col + right_for;
  2289.       col_end = col_start + 8;
  2290.       cfirst = 0;
  2291.     }
  2292.  
  2293.     for (rr = row_start; rr < row_end; rr++) {
  2294.       rindex1 = past + (rr * row_size) + col_start;
  2295.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2296.       for (cc = col_start; cc < col_end; cc++) {
  2297.     *index++ = *rindex1++;
  2298.       }
  2299.     }
  2300.  
  2301.     if (illegalBlock & 0x1) {
  2302.       for (rr = rlast -1; rr >=0; rr--) {
  2303.     index = dest + ((row + rr) * row_size) + col;
  2304.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2305.     for (cc = 0; cc < 8; cc ++) {
  2306.       *index++ = *rindex1++;
  2307.     }
  2308.       }
  2309.     }
  2310.     else if (illegalBlock & 0x4) {
  2311.       for (rr = rlast+1; rr < 8; rr++) {
  2312.     index = dest + ((row + rr) * row_size) + col;
  2313.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2314.     for (cc = 0; cc < 8; cc ++) {
  2315.       *index++ = *rindex1++;
  2316.     }
  2317.       }
  2318.     }
  2319.  
  2320.     if (illegalBlock & 0x2) {
  2321.       for (cc = clast+1; cc < 8; cc++) {
  2322.     index = dest + (row * row_size) + (col + cc);
  2323.     rindex1 = dest + (row * row_size) + (col + clast);
  2324.     for (rr = 0; rr < 8; rr++) {
  2325.       *index = *rindex1;
  2326.       index += row_size;
  2327.       rindex1 += row_size;
  2328.     }
  2329.       }
  2330.     }
  2331.     else if (illegalBlock & 0x8) {
  2332.       for (cc = clast-1; cc >= 0; cc--) {
  2333.     index = dest + (row * row_size) + (col + cc);
  2334.     rindex1 = dest + (row * row_size) + (col + clast);
  2335.     for (rr = 0; rr < 8; rr++) {
  2336.       *index = *rindex1;
  2337.       index += row_size;
  2338.       rindex1 += row_size;
  2339.     }
  2340.       }
  2341.     }
  2342.  
  2343.     if (!zflag) {
  2344.       for (rr = 0; rr < 8; rr++) {
  2345.     index = dest + (row*row_size) + col;
  2346.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2347.     index[0] += blockvals[0];
  2348.     index[1] += blockvals[1];
  2349.     index[2] += blockvals[2];
  2350.     index[3] += blockvals[3];
  2351.     index[4] += blockvals[4];
  2352.     index[5] += blockvals[5];
  2353.     index[6] += blockvals[6];
  2354.     index[7] += blockvals[7];
  2355.       }
  2356.     }
  2357.   }
  2358.   else {
  2359.  
  2360. #endif
  2361.  
  2362.     index = dest + (row * row_size) + col;
  2363.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  2364.     
  2365.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2366.     
  2367.     /*
  2368.      * Calculate predictive pixel value based on motion vectors and copy to
  2369.      * dest plane.
  2370.      */
  2371.     
  2372.     if ((!down_half_for) && (!right_half_for)) {
  2373.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2374.       if (!zflag)
  2375.     for (rr = 0; rr < 4; rr++) {
  2376.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2377.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2378.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2379.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2380.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2381.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2382.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2383.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2384.       index += row_size;
  2385.       rindex1 += row_size;
  2386.       
  2387.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2388.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2389.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2390.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2391.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2392.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2393.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2394.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2395.       blockvals += 16;
  2396.       index += row_size;
  2397.       rindex1 += row_size;
  2398.     }
  2399.       else {
  2400.     if (right_for & 0x1) {
  2401.       /* No alignment, use bye copy */
  2402.       for (rr = 0; rr < 4; rr++) {
  2403.         index[0] = rindex1[0];
  2404.         index[1] = rindex1[1];
  2405.         index[2] = rindex1[2];
  2406.         index[3] = rindex1[3];
  2407.         index[4] = rindex1[4];
  2408.         index[5] = rindex1[5];
  2409.         index[6] = rindex1[6];
  2410.         index[7] = rindex1[7];
  2411.         index += row_size;
  2412.         rindex1 += row_size;
  2413.         
  2414.         index[0] = rindex1[0];
  2415.         index[1] = rindex1[1];
  2416.         index[2] = rindex1[2];
  2417.         index[3] = rindex1[3];
  2418.         index[4] = rindex1[4];
  2419.         index[5] = rindex1[5];
  2420.         index[6] = rindex1[6];
  2421.         index[7] = rindex1[7];
  2422.         index += row_size;
  2423.         rindex1 += row_size;
  2424.       }
  2425.     } else if (right_for & 0x2) {
  2426.       /* Half-word bit aligned, use 16 bit copy */
  2427.       short *src = (short *)rindex1;
  2428.       short *dest = (short *)index;
  2429.       row_size >>= 1;
  2430.       for (rr = 0; rr < 4; rr++) {
  2431.         dest[0] = src[0];
  2432.         dest[1] = src[1];
  2433.         dest[2] = src[2];
  2434.         dest[3] = src[3];
  2435.         dest += row_size;
  2436.         src += row_size;
  2437.         
  2438.         dest[0] = src[0];
  2439.         dest[1] = src[1];
  2440.         dest[2] = src[2];
  2441.         dest[3] = src[3];
  2442.         dest += row_size;
  2443.         src += row_size;
  2444.       }
  2445.     } else {
  2446.       /* Word aligned, use 32 bit copy */
  2447.       int *src = (int *)rindex1;
  2448.       int *dest = (int *)index;
  2449.       row_size >>= 2;
  2450.       for (rr = 0; rr < 4; rr++) {
  2451.         dest[0] = src[0];
  2452.         dest[1] = src[1];
  2453.         dest += row_size;
  2454.         src += row_size;
  2455.         
  2456.         dest[0] = src[0];
  2457.         dest[1] = src[1];
  2458.         dest += row_size;
  2459.         src += row_size;
  2460.       }
  2461.     }
  2462.       }
  2463.     } else {
  2464.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2465.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2466.       if (!zflag)
  2467.     for (rr = 0; rr < 4; rr++) {
  2468.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2469.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2470.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2471.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2472.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2473.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2474.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2475.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2476.       index += row_size;
  2477.       rindex1 += row_size;
  2478.       rindex2 += row_size;
  2479.       
  2480.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2481.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2482.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2483.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2484.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2485.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2486.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2487.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2488.       blockvals += 16;
  2489.       index += row_size;
  2490.       rindex1 += row_size;
  2491.       rindex2 += row_size;
  2492.     }
  2493.       else
  2494.     for (rr = 0; rr < 4; rr++) {
  2495.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2496.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2497.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2498.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2499.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2500.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2501.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2502.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2503.       index += row_size;
  2504.       rindex1 += row_size;
  2505.       rindex2 += row_size;
  2506.       
  2507.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2508.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2509.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2510.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2511.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2512.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2513.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2514.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2515.       index += row_size;
  2516.       rindex1 += row_size;
  2517.       rindex2 += row_size;
  2518.     }
  2519.     }
  2520.  
  2521. #ifdef LOOSE_MPEG
  2522.   }
  2523. #endif
  2524. }
  2525.  
  2526.  
  2527. /*
  2528.  *--------------------------------------------------------------
  2529.  *
  2530.  * ReconBMBlock --
  2531.  *
  2532.  *    Reconstructs back predicted macroblocks.
  2533.  *
  2534.  * Results:
  2535.  *      None.
  2536.  *
  2537.  * Side effects:
  2538.  *      None.
  2539.  *
  2540.  *--------------------------------------------------------------
  2541.  */
  2542.  
  2543. static void
  2544. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2545.   VidStream *vid_stream;
  2546.   int bnum, recon_right_back, recon_down_back, zflag;
  2547. {
  2548.   int mb_row, mb_col, row, col, row_size, rr;
  2549.   unsigned char *dest, *future;
  2550.   int right_back, down_back, right_half_back, down_half_back;
  2551.   unsigned char *rindex1, *rindex2;
  2552.   unsigned char *index;
  2553.   short int *blockvals;
  2554.  
  2555. #ifdef LOOSE_MPEG
  2556.   int illegalBlock = 0;
  2557.   int maxx, maxy;
  2558.   int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
  2559. #endif
  2560.  
  2561.   /* Calculate macroblock row and column from address. */
  2562.  
  2563.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2564.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2565.  
  2566.   /* If block is luminance block... */
  2567.  
  2568.   if (bnum < 4) {
  2569.  
  2570.     /* Calculate right_back, down_bakc motion vectors. */
  2571.  
  2572.     right_back = recon_right_back >> 1;
  2573.     down_back = recon_down_back >> 1;
  2574.     right_half_back = recon_right_back & 0x1;
  2575.     down_half_back = recon_down_back & 0x1;
  2576.  
  2577.     /* Set dest to luminance plane of current pict image. */
  2578.  
  2579.     dest = vid_stream->current->luminance;
  2580.  
  2581.     /*
  2582.      * If future frame exists, set future to luminance plane of future frame.
  2583.      */
  2584.  
  2585.     if (vid_stream->future != NULL)
  2586.       future = vid_stream->future->luminance;
  2587.  
  2588.     /* Establish row size. */
  2589.  
  2590.     row_size = vid_stream->mb_width << 4;
  2591.  
  2592.     /* Calculate row,col of upper left pixel in block. */
  2593.  
  2594.     row = mb_row << 4;
  2595.     col = mb_col << 4;
  2596.     if (bnum > 1)
  2597.       row += 8;
  2598.     if (bnum % 2)
  2599.       col += 8;
  2600.  
  2601. #ifdef LOOSE_MPEG
  2602.  
  2603.     /* Check for block illegality. */
  2604.  
  2605.     maxx = lmaxx; maxy = lmaxy;
  2606.  
  2607.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2608.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2609.     
  2610.     if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
  2611.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2612.  
  2613. #endif
  2614.  
  2615.   }
  2616.   /* Otherwise, block is NOT luminance block, ... */
  2617.  
  2618.   else {
  2619.  
  2620.     /* Construct motion vectors. */
  2621.  
  2622.     recon_right_back /= 2;
  2623.     recon_down_back /= 2;
  2624.     right_back = recon_right_back >> 1;
  2625.     down_back = recon_down_back >> 1;
  2626.     right_half_back = recon_right_back & 0x1;
  2627.     down_half_back = recon_down_back & 0x1;
  2628.  
  2629.     /* Establish row size. */
  2630.  
  2631.     row_size = vid_stream->mb_width << 3;
  2632.  
  2633.     /* Calculate row,col of upper left pixel in block. */
  2634.  
  2635.     row = mb_row << 3;
  2636.     col = mb_col << 3;
  2637.  
  2638. #ifdef LOOSE_MPEG
  2639.  
  2640.     /* Check for block illegality. */
  2641.  
  2642.     maxx = cmaxx; maxy = cmaxy;
  2643.  
  2644.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2645.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2646.  
  2647.     if (col + right_back + 7 > maxx) illegalBlock  |= 0x2;
  2648.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2649.  
  2650. #endif
  2651.  
  2652.     /* If block is Cr block... */
  2653.  
  2654.     if (bnum == 4) {
  2655.  
  2656.       /* Set dest to Cr plane of current pict image. */
  2657.  
  2658.       dest = vid_stream->current->Cr;
  2659.  
  2660.       /*
  2661.        * If future frame exists, set future to Cr plane of future image.
  2662.        */
  2663.  
  2664.       if (vid_stream->future != NULL)
  2665.     future = vid_stream->future->Cr;
  2666.     }
  2667.     /* Otherwise, block is Cb block... */
  2668.  
  2669.     else {
  2670.  
  2671.       /* Set dest to Cb plane of current pict image. */
  2672.  
  2673.       dest = vid_stream->current->Cb;
  2674.  
  2675.       /*
  2676.        * If future frame exists, set future to Cb plane of future frame.
  2677.        */
  2678.  
  2679.       if (vid_stream->future != NULL)
  2680.     future = vid_stream->future->Cb;
  2681.     }
  2682.   }
  2683.  
  2684.   /* For each pixel in block do... */
  2685.  
  2686. #ifdef LOOSE_MPEG
  2687.  
  2688.   if (illegalBlock) {
  2689.     if (illegalBlock & 0x1) {
  2690.       row_start = 0;
  2691.       row_end = row+down_back+8;
  2692.       rfirst = rlast = 8 - row_end;
  2693.     }
  2694.     else if (illegalBlock & 0x4) {
  2695.       row_start = row + down_back;
  2696.       row_end = maxy+1;
  2697.       rlast = row_end - row_start - 1;
  2698.       rfirst = 0;
  2699.     }
  2700.     else {
  2701.       row_start = row+down_back;
  2702.       row_end = row_start+8;
  2703.       rfirst = 0;
  2704.     }
  2705.  
  2706.     if (illegalBlock & 0x8) {
  2707.       col_start = 0;
  2708.       col_end = col + right_back + 8;
  2709.       cfirst = clast = 8 - col_end;
  2710.     }
  2711.     else if (illegalBlock & 0x2) {
  2712.       col_start = col + right_back;
  2713.       col_end = maxx + 1;
  2714.       clast = col_end - col_start - 1;
  2715.       cfirst = 0;
  2716.     }
  2717.     else {
  2718.       col_start = col + right_back;
  2719.       col_end = col_start + 8;
  2720.       cfirst = 0;
  2721.     }
  2722.  
  2723.     for (rr = row_start; rr < row_end; rr++) {
  2724.       rindex1 = future + (rr * row_size) + col_start;
  2725.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2726.       for (cc = col_start; cc < col_end; cc++) {
  2727.     *index++ = *rindex1++;
  2728.       }
  2729.     }
  2730.  
  2731.     if (illegalBlock & 0x1) {
  2732.       for (rr = rlast -1; rr >=0; rr--) {
  2733.     index = dest + ((row + rr) * row_size) + col;
  2734.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2735.     for (cc = 0; cc < 8; cc ++) {
  2736.       *index++ = *rindex1++;
  2737.     }
  2738.       }
  2739.     }
  2740.     else if (illegalBlock & 0x4) {
  2741.       for (rr = rlast+1; rr < 8; rr++) {
  2742.     index = dest + ((row + rr) * row_size) + col;
  2743.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2744.     for (cc = 0; cc < 8; cc ++) {
  2745.       *index++ = *rindex1++;
  2746.     }
  2747.       }
  2748.     }
  2749.  
  2750.     if (illegalBlock & 0x2) {
  2751.       for (cc = clast+1; cc < 8; cc++) {
  2752.     index = dest + (row * row_size) + (col + cc);
  2753.     rindex1 = dest + (row * row_size) + (col + clast);
  2754.     for (rr = 0; rr < 8; rr++) {
  2755.       *index = *rindex1;
  2756.       index += row_size;
  2757.       rindex1 += row_size;
  2758.     }
  2759.       }
  2760.     }
  2761.     else if (illegalBlock & 0x8) {
  2762.       for (cc = clast-1; cc >= 0; cc--) {
  2763.     index = dest + (row * row_size) + (col + cc);
  2764.     rindex1 = dest + (row * row_size) + (col + clast);
  2765.     for (rr = 0; rr < 8; rr++) {
  2766.       *index = *rindex1;
  2767.       index += row_size;
  2768.       rindex1 += row_size;
  2769.     }
  2770.       }
  2771.     }
  2772.  
  2773.     if (!zflag) {
  2774.       for (rr = 0; rr < 8; rr++) {
  2775.     index = dest + (row*row_size) + col;
  2776.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2777.     index[0] += blockvals[0];
  2778.     index[1] += blockvals[1];
  2779.     index[2] += blockvals[2];
  2780.     index[3] += blockvals[3];
  2781.     index[4] += blockvals[4];
  2782.     index[5] += blockvals[5];
  2783.     index[6] += blockvals[6];
  2784.     index[7] += blockvals[7];
  2785.       }
  2786.     }
  2787.   }
  2788.   else {
  2789.  
  2790. #endif
  2791.     
  2792.     index = dest + (row * row_size) + col;
  2793.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2794.  
  2795.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2796.  
  2797.     if ((!right_half_back) && (!down_half_back)) {
  2798.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2799.       if (!zflag)
  2800.     for (rr = 0; rr < 4; rr++) {
  2801.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2802.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2803.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2804.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2805.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2806.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2807.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2808.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2809.       index += row_size;
  2810.       rindex1 += row_size;
  2811.       
  2812.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2813.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2814.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2815.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2816.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2817.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2818.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2819.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2820.       blockvals += 16;
  2821.       index += row_size;
  2822.       rindex1 += row_size;
  2823.     }
  2824.       else {
  2825.     if (right_back & 0x1) {
  2826.       /* No alignment, use bye copy */
  2827.       for (rr = 0; rr < 4; rr++) {
  2828.         index[0] = rindex1[0];
  2829.         index[1] = rindex1[1];
  2830.         index[2] = rindex1[2];
  2831.         index[3] = rindex1[3];
  2832.         index[4] = rindex1[4];
  2833.         index[5] = rindex1[5];
  2834.         index[6] = rindex1[6];
  2835.         index[7] = rindex1[7];
  2836.         index += row_size;
  2837.         rindex1 += row_size;
  2838.         
  2839.         index[0] = rindex1[0];
  2840.         index[1] = rindex1[1];
  2841.         index[2] = rindex1[2];
  2842.         index[3] = rindex1[3];
  2843.         index[4] = rindex1[4];
  2844.         index[5] = rindex1[5];
  2845.         index[6] = rindex1[6];
  2846.         index[7] = rindex1[7];
  2847.         index += row_size;
  2848.         rindex1 += row_size;
  2849.       }
  2850.     } else if (right_back & 0x2) {
  2851.       /* Half-word bit aligned, use 16 bit copy */
  2852.       short *src = (short *)rindex1;
  2853.       short *dest = (short *)index;
  2854.       row_size >>= 1;
  2855.       for (rr = 0; rr < 4; rr++) {
  2856.         dest[0] = src[0];
  2857.         dest[1] = src[1];
  2858.         dest[2] = src[2];
  2859.         dest[3] = src[3];
  2860.         dest += row_size;
  2861.         src += row_size;
  2862.         
  2863.         dest[0] = src[0];
  2864.         dest[1] = src[1];
  2865.         dest[2] = src[2];
  2866.         dest[3] = src[3];
  2867.         dest += row_size;
  2868.         src += row_size;
  2869.       }
  2870.     } else {
  2871.       /* Word aligned, use 32 bit copy */
  2872.       int *src = (int *)rindex1;
  2873.       int *dest = (int *)index;
  2874.       row_size >>= 2;
  2875.       for (rr = 0; rr < 4; rr++) {
  2876.         dest[0] = src[0];
  2877.         dest[1] = src[1];
  2878.         dest += row_size;
  2879.         src += row_size;
  2880.         
  2881.         dest[0] = src[0];
  2882.         dest[1] = src[1];
  2883.         dest += row_size;
  2884.         src += row_size;
  2885.       }
  2886.     }
  2887.       }
  2888.     } else {
  2889.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2890.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2891.       if (!zflag)
  2892.     for (rr = 0; rr < 4; rr++) {
  2893.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2894.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2895.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2896.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2897.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2898.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2899.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2900.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2901.       index += row_size;
  2902.       rindex1 += row_size;
  2903.       rindex2 += row_size;
  2904.       
  2905.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2906.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2907.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2908.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2909.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2910.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2911.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2912.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2913.       blockvals += 16;
  2914.       index += row_size;
  2915.       rindex1 += row_size;
  2916.       rindex2 += row_size;
  2917.     }
  2918.       else
  2919.     for (rr = 0; rr < 4; rr++) {
  2920.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2921.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2922.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2923.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2924.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2925.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2926.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2927.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2928.       index += row_size;
  2929.       rindex1 += row_size;
  2930.       rindex2 += row_size;
  2931.       
  2932.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2933.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2934.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2935.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2936.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2937.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2938.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2939.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2940.       index += row_size;
  2941.       rindex1 += row_size;
  2942.       rindex2 += row_size;
  2943.     }
  2944.     }
  2945.  
  2946. #ifdef LOOSE_MPEG
  2947.   }
  2948. #endif
  2949.  
  2950. }
  2951.  
  2952.  
  2953. /*
  2954.  *--------------------------------------------------------------
  2955.  *
  2956.  * ReconBiMBlock --
  2957.  *
  2958.  *    Reconstructs bidirectionally predicted macroblocks.
  2959.  *
  2960.  * Results:
  2961.  *      None.
  2962.  *
  2963.  * Side effects:
  2964.  *      None.
  2965.  *
  2966.  *--------------------------------------------------------------
  2967.  */
  2968.  
  2969. static void
  2970. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  2971.           recon_right_back, recon_down_back, zflag)
  2972.   VidStream *vid_stream;
  2973.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  2974.   int zflag;
  2975. {
  2976.   int mb_row, mb_col, row, col, row_size, rr;
  2977.   unsigned char *dest, *past, *future;
  2978.   int right_for, down_for, right_half_for, down_half_for;
  2979.   int right_back, down_back, right_half_back, down_half_back;
  2980.   unsigned char *index, *rindex1, *bindex1;
  2981.   short int *blockvals;
  2982.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  2983.  
  2984. #ifdef LOOSE_MPEG
  2985.   int illegal_forw = 0;
  2986.   int illegal_back = 0;
  2987. #endif
  2988.  
  2989.   /* Calculate macroblock row and column from address. */
  2990.  
  2991.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2992.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2993.  
  2994.   /* If block is luminance block... */
  2995.  
  2996.   if (bnum < 4) {
  2997.  
  2998.     /*
  2999.      * Calculate right_for, down_for, right_half_for, down_half_for,
  3000.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  3001.      * vectors.
  3002.      */
  3003.  
  3004.     right_for = recon_right_for >> 1;
  3005.     down_for = recon_down_for >> 1;
  3006.     right_half_for = recon_right_for & 0x1;
  3007.     down_half_for = recon_down_for & 0x1;
  3008.  
  3009.     right_back = recon_right_back >> 1;
  3010.     down_back = recon_down_back >> 1;
  3011.     right_half_back = recon_right_back & 0x1;
  3012.     down_half_back = recon_down_back & 0x1;
  3013.  
  3014.     /* Set dest to luminance plane of current pict image. */
  3015.  
  3016.     dest = vid_stream->current->luminance;
  3017.  
  3018.     /* If past frame exists, set past to luminance plane of past frame. */
  3019.  
  3020.     if (vid_stream->past != NULL)
  3021.       past = vid_stream->past->luminance;
  3022.  
  3023.     /*
  3024.      * If future frame exists, set future to luminance plane of future frame.
  3025.      */
  3026.  
  3027.     if (vid_stream->future != NULL)
  3028.       future = vid_stream->future->luminance;
  3029.  
  3030.     /* Establish row size. */
  3031.  
  3032.     row_size = (vid_stream->mb_width << 4);
  3033.  
  3034.     /* Calculate row,col of upper left pixel in block. */
  3035.  
  3036.     row = (mb_row << 4);
  3037.     col = (mb_col << 4);
  3038.     if (bnum > 1)
  3039.       row += 8;
  3040.     if (bnum & 0x01)
  3041.       col += 8;
  3042.  
  3043.     forw_col_start = col + right_for;
  3044.     forw_row_start = row + down_for;
  3045.  
  3046.     back_col_start = col + right_back;
  3047.     back_row_start = row + down_back;
  3048.  
  3049. #ifdef LOOSE_MPEG
  3050.  
  3051.     /* Check for illegal pred. blocks. */
  3052.  
  3053.  
  3054.     if (forw_col_start+8 > lmaxx) illegal_forw = 1;
  3055.     else if (forw_col_start < 0) illegal_forw = 1;
  3056.  
  3057.     if (forw_row_start+8 > lmaxy) illegal_forw = 1;
  3058.     else if (forw_row_start < 0) illegal_forw = 1;
  3059.  
  3060.     if (back_col_start+8 > lmaxx) illegal_back = 1;
  3061.     else if (back_col_start < 0) illegal_back = 1;
  3062.  
  3063.     if (back_row_start+8 > lmaxy) illegal_back = 1;
  3064.     else if (back_row_start < 0) illegal_back = 1;
  3065.  
  3066. #endif
  3067.  
  3068.   }
  3069.   /* Otherwise, block is NOT luminance block, ... */
  3070.  
  3071.   else {
  3072.  
  3073.     /* Construct motion vectors. */
  3074.  
  3075.     recon_right_for /= 2;
  3076.     recon_down_for /= 2;
  3077.     right_for = recon_right_for >> 1;
  3078.     down_for = recon_down_for >> 1;
  3079.     right_half_for = recon_right_for & 0x1;
  3080.     down_half_for = recon_down_for & 0x1;
  3081.  
  3082.     recon_right_back /= 2;
  3083.     recon_down_back /= 2;
  3084.     right_back = recon_right_back >> 1;
  3085.     down_back = recon_down_back >> 1;
  3086.     right_half_back = recon_right_back & 0x1;
  3087.     down_half_back = recon_down_back & 0x1;
  3088.  
  3089.     /* Establish row size. */
  3090.  
  3091.     row_size = (vid_stream->mb_width << 3);
  3092.  
  3093.     /* Calculate row,col of upper left pixel in block. */
  3094.  
  3095.     row = (mb_row << 3);
  3096.     col = (mb_col << 3);
  3097.  
  3098.     forw_col_start = col + right_for;
  3099.     forw_row_start = row + down_for;
  3100.  
  3101.     back_col_start = col + right_back;
  3102.     back_row_start = row + down_back;
  3103.  
  3104. #ifdef LOOSE_MPEG
  3105.  
  3106.     /* Check for illegal pred. blocks. */
  3107.  
  3108.     if (forw_col_start+8 > cmaxx) illegal_forw = 1;
  3109.     else if (forw_col_start < 0) illegal_forw = 1;
  3110.  
  3111.     if (forw_row_start+8 > cmaxy) illegal_forw = 1;
  3112.     else if (forw_row_start < 0) illegal_forw = 1;
  3113.  
  3114.     if (back_col_start+8 > cmaxx) illegal_back = 1;
  3115.     else if (back_col_start < 0) illegal_back = 1;
  3116.     
  3117.     if (back_row_start+8 > cmaxy) illegal_back = 1;
  3118.     else if (back_row_start < 0) illegal_back = 1;
  3119.  
  3120. #endif
  3121.     
  3122.     /* If block is Cr block... */
  3123.  
  3124.     if (bnum == 4) {
  3125.  
  3126.       /* Set dest to Cr plane of current pict image. */
  3127.  
  3128.       dest = vid_stream->current->Cr;
  3129.  
  3130.       /* If past frame exists, set past to Cr plane of past image. */
  3131.  
  3132.       if (vid_stream->past != NULL)
  3133.     past = vid_stream->past->Cr;
  3134.  
  3135.       /*
  3136.        * If future frame exists, set future to Cr plane of future image.
  3137.        */
  3138.  
  3139.       if (vid_stream->future != NULL)
  3140.     future = vid_stream->future->Cr;
  3141.     }
  3142.     /* Otherwise, block is Cb block... */
  3143.  
  3144.     else {
  3145.  
  3146.       /* Set dest to Cb plane of current pict image. */
  3147.  
  3148.       dest = vid_stream->current->Cb;
  3149.  
  3150.       /* If past frame exists, set past to Cb plane of past frame. */
  3151.  
  3152.       if (vid_stream->past != NULL)
  3153.     past = vid_stream->past->Cb;
  3154.  
  3155.       /*
  3156.        * If future frame exists, set future to Cb plane of future frame.
  3157.        */
  3158.  
  3159.       if (vid_stream->future != NULL)
  3160.     future = vid_stream->future->Cb;
  3161.     }
  3162.   }
  3163.  
  3164.   /* For each pixel in block... */
  3165.  
  3166.   index = dest + (row * row_size) + col;
  3167.  
  3168. #ifdef LOOSE_MPEG
  3169.   if (illegal_forw) 
  3170.     rindex1 = future + back_row_start * row_size + back_col_start;
  3171.   else 
  3172. #endif
  3173.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  3174.  
  3175. #ifdef LOOSE_MPEG
  3176.   if (illegal_back) 
  3177.     bindex1 = past + forw_row_start * row_size + forw_col_start;
  3178.   else 
  3179. #endif
  3180.     bindex1 = future + back_row_start * row_size + back_col_start;
  3181.  
  3182.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  3183.  
  3184.   {
  3185.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3186.   if (!zflag)
  3187.     for (rr = 0; rr < 4; rr++) {
  3188.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  3189.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  3190.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  3191.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  3192.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  3193.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  3194.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  3195.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  3196.       index += row_size;
  3197.       rindex1 += row_size;
  3198.       bindex1 += row_size;
  3199.  
  3200.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  3201.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  3202.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  3203.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  3204.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  3205.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  3206.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  3207.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  3208.       blockvals += 16;
  3209.       index += row_size;
  3210.       rindex1 += row_size;
  3211.       bindex1 += row_size;
  3212.     }
  3213.  
  3214.   else
  3215.     for (rr = 0; rr < 4; rr++) {
  3216.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3217.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3218.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3219.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3220.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3221.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3222.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3223.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3224.       index += row_size;
  3225.       rindex1 += row_size;
  3226.       bindex1 += row_size;
  3227.  
  3228.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3229.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3230.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3231.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3232.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3233.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3234.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3235.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3236.       index += row_size;
  3237.       rindex1 += row_size;
  3238.       bindex1 += row_size;
  3239.     }
  3240.   }
  3241. }
  3242.  
  3243. /*
  3244.  *--------------------------------------------------------------
  3245.  *
  3246.  * ProcessSkippedPFrameMBlocks --
  3247.  *
  3248.  *    Processes skipped macroblocks in P frames.
  3249.  *
  3250.  * Results:
  3251.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3252.  *      in current pict image for skipped macroblocks.
  3253.  *
  3254.  * Side effects:
  3255.  *    Pixel values in pict image changed.
  3256.  *
  3257.  *--------------------------------------------------------------
  3258.  */
  3259.  
  3260. static void
  3261. ProcessSkippedPFrameMBlocks(vid_stream)
  3262.   VidStream *vid_stream;
  3263. {
  3264.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3265.   int addr, row_incr, half_row_incr, crow, ccol;
  3266.   int *dest, *src, *dest1, *src1;
  3267.  
  3268.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3269.  
  3270.   row_size = vid_stream->mb_width << 4;
  3271.   half_row = (row_size >> 1);
  3272.   row_incr = row_size >> 2;
  3273.   half_row_incr = half_row >> 2;
  3274.  
  3275.   /* For each skipped macroblock, do... */
  3276.  
  3277.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3278.        addr < vid_stream->mblock.mb_address; addr++) {
  3279.  
  3280.     /* Calculate macroblock row and col. */
  3281.  
  3282.     mb_row = addr / vid_stream->mb_width;
  3283.     mb_col = addr % vid_stream->mb_width;
  3284.  
  3285.     /* Calculate upper left pixel row,col for luminance plane. */
  3286.  
  3287.     row = mb_row << 4;
  3288.     col = mb_col << 4;
  3289.  
  3290.  
  3291.     /* For each row in macroblock luminance plane... */
  3292.  
  3293.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3294.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  3295.  
  3296.     for (rr = 0; rr < 8; rr++) {
  3297.  
  3298.       /* Copy pixel values from last I or P picture. */
  3299.  
  3300.       dest[0] = src[0];
  3301.       dest[1] = src[1];
  3302.       dest[2] = src[2];
  3303.       dest[3] = src[3];
  3304.       dest += row_incr;
  3305.       src += row_incr;
  3306.  
  3307.       dest[0] = src[0];
  3308.       dest[1] = src[1];
  3309.       dest[2] = src[2];
  3310.       dest[3] = src[3];
  3311.       dest += row_incr;
  3312.       src += row_incr;
  3313.     }
  3314.  
  3315.     /*
  3316.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  3317.      * planes.
  3318.      */
  3319.  
  3320.     crow = row >> 1;
  3321.     ccol = col >> 1;
  3322.  
  3323.     /* For each row in Cr, and Cb planes... */
  3324.  
  3325.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3326.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  3327.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3328.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  3329.  
  3330.     for (rr = 0; rr < 4; rr++) {
  3331.  
  3332.       /* Copy pixel values from last I or P picture. */
  3333.  
  3334.       dest[0] = src[0];
  3335.       dest[1] = src[1];
  3336.  
  3337.       dest1[0] = src1[0];
  3338.       dest1[1] = src1[1];
  3339.  
  3340.       dest += half_row_incr;
  3341.       src += half_row_incr;
  3342.       dest1 += half_row_incr;
  3343.       src1 += half_row_incr;
  3344.  
  3345.       dest[0] = src[0];
  3346.       dest[1] = src[1];
  3347.  
  3348.       dest1[0] = src1[0];
  3349.       dest1[1] = src1[1];
  3350.  
  3351.       dest += half_row_incr;
  3352.       src += half_row_incr;
  3353.       dest1 += half_row_incr;
  3354.       src1 += half_row_incr;
  3355.     }
  3356.   }
  3357.  
  3358.   vid_stream->mblock.recon_right_for_prev = 0;
  3359.   vid_stream->mblock.recon_down_for_prev = 0;
  3360. }
  3361.  
  3362.  
  3363.  
  3364.  
  3365. /*
  3366.  *--------------------------------------------------------------
  3367.  *
  3368.  * ProcessSkippedBFrameMBlocks --
  3369.  *
  3370.  *    Processes skipped macroblocks in B frames.
  3371.  *
  3372.  * Results:
  3373.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3374.  *      in current pict image for skipped macroblocks.
  3375.  *
  3376.  * Side effects:
  3377.  *    Pixel values in pict image changed.
  3378.  *
  3379.  *--------------------------------------------------------------
  3380.  */
  3381.  
  3382. static void
  3383. ProcessSkippedBFrameMBlocks(vid_stream)
  3384.   VidStream *vid_stream;
  3385. {
  3386.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3387.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  3388.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  3389.   int addr, right_for, down_for;
  3390.   int recon_right_for, recon_down_for;
  3391.   int recon_right_back, recon_down_back;
  3392.   int right_back, down_back;
  3393.   int c_right_for, c_down_for;
  3394.   int c_right_back, c_down_back;
  3395.   unsigned char forw_lum[256];
  3396.   unsigned char forw_cr[64], forw_cb[64];
  3397.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  3398.   int row_incr, half_row_incr;
  3399.   int ccol, crow;
  3400.  
  3401.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3402.  
  3403.   row_size = vid_stream->mb_width << 4;
  3404.   half_row = (row_size >> 1);
  3405.   row_incr = row_size >> 2;
  3406.   half_row_incr =  half_row >> 2;
  3407.  
  3408.   /* Establish motion vector codes based on full pixel flag. */
  3409.  
  3410.   if (vid_stream->picture.full_pel_forw_vector) {
  3411.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  3412.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  3413.   } else {
  3414.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  3415.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  3416.   }
  3417.  
  3418.   if (vid_stream->picture.full_pel_back_vector) {
  3419.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  3420.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  3421.   } else {
  3422.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  3423.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  3424.   }
  3425.  
  3426.   /* If only one motion vector, do display copy, else do full
  3427.      calculation. 
  3428.   */
  3429.  
  3430.   /* Calculate motion vectors. */
  3431.   
  3432.   if (vid_stream->mblock.bpict_past_forw) {
  3433.     right_for = recon_right_for >> 1;
  3434.     down_for = recon_down_for >> 1;
  3435.     right_half_for = recon_right_for & 0x1;
  3436.     down_half_for = recon_down_for & 0x1;
  3437.     
  3438.     recon_right_for /= 2;
  3439.     recon_down_for /= 2;
  3440.     c_right_for = recon_right_for >> 1;
  3441.     c_down_for = recon_down_for >> 1;
  3442.     c_right_half_for = recon_right_for & 0x1;
  3443.     c_down_half_for = recon_down_for & 0x1;
  3444.     
  3445.   }
  3446.   if (vid_stream->mblock.bpict_past_back) {
  3447.     right_back = recon_right_back >> 1;
  3448.     down_back = recon_down_back >> 1;
  3449.     right_half_back = recon_right_back & 0x1;
  3450.     down_half_back = recon_down_back & 0x1;
  3451.     
  3452.     recon_right_back /= 2;
  3453.     recon_down_back /= 2;
  3454.     c_right_back = recon_right_back >> 1;
  3455.     c_down_back = recon_down_back >> 1;
  3456.     c_right_half_back = recon_right_back & 0x1;
  3457.     c_down_half_back = recon_down_back & 0x1;
  3458.     
  3459.   }
  3460.   /* For each skipped macroblock, do... */
  3461.   
  3462.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3463.        addr < vid_stream->mblock.mb_address; addr++) {
  3464.     
  3465.     /* Calculate macroblock row and col. */
  3466.     
  3467.     mb_row = addr / vid_stream->mb_width;
  3468.     mb_col = addr % vid_stream->mb_width;
  3469.     
  3470.     /* Calculate upper left pixel row,col for luminance plane. */
  3471.     
  3472.     row = mb_row << 4;
  3473.     col = mb_col << 4;
  3474.     crow = row / 2;
  3475.     ccol = col / 2;
  3476.     
  3477.     /* If forward predicted, calculate prediction values. */
  3478.     
  3479.     if (vid_stream->mblock.bpict_past_forw) {
  3480.       
  3481.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  3482.             row, col, row_size, right_for, down_for,
  3483.             right_half_for, down_half_for, 16);
  3484.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  3485.             ccol, half_row,
  3486.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3487.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  3488.             ccol, half_row,
  3489.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3490.     }
  3491.     /* If back predicted, calculate prediction values. */
  3492.     
  3493.     if (vid_stream->mblock.bpict_past_back) {
  3494.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  3495.             row, col, row_size, right_back, down_back,
  3496.             right_half_back, down_half_back, 16);
  3497.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  3498.             ccol, half_row,
  3499.             c_right_back, c_down_back,
  3500.             c_right_half_back, c_down_half_back, 8);
  3501.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  3502.             ccol, half_row,
  3503.             c_right_back, c_down_back,
  3504.             c_right_half_back, c_down_half_back, 8);
  3505.     }
  3506.     if (vid_stream->mblock.bpict_past_forw &&
  3507.     !vid_stream->mblock.bpict_past_back) {
  3508.       
  3509.       int *dest, *dest1;
  3510.       int *src, *src1;
  3511.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3512.       src = (int *)forw_lum;
  3513.       
  3514.       for (rr = 0; rr < 16; rr++) {
  3515.     
  3516.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  3517.     dest[0] = src[0];
  3518.     dest[1] = src[1];
  3519.     dest[2] = src[2];
  3520.     dest[3] = src[3];
  3521.     dest += row_incr;
  3522.     src += 4;
  3523.       }
  3524.       
  3525.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3526.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3527.       src = (int *)forw_cr;
  3528.       src1 = (int *)forw_cb;
  3529.       
  3530.       for (rr = 0; rr < 8; rr++) {
  3531.     /*
  3532.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  3533.      * 8);
  3534.      */
  3535.     
  3536.     dest[0] = src[0];
  3537.     dest[1] = src[1];
  3538.     
  3539.     dest1[0] = src1[0];
  3540.     dest1[1] = src1[1];
  3541.     
  3542.     dest += half_row_incr;
  3543.     dest1 += half_row_incr;
  3544.     src += 2;
  3545.     src1 += 2;
  3546.       }
  3547.     } else if (vid_stream->mblock.bpict_past_back &&
  3548.            !vid_stream->mblock.bpict_past_forw) {
  3549.       
  3550.       int *src, *src1;
  3551.       int *dest, *dest1;
  3552.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3553.       src = (int *)back_lum;
  3554.       
  3555.       for (rr = 0; rr < 16; rr++) {
  3556.     dest[0] = src[0];
  3557.     dest[1] = src[1];
  3558.     dest[2] = src[2];
  3559.     dest[3] = src[3];
  3560.     dest += row_incr;
  3561.     src += 4;
  3562.       }
  3563.       
  3564.       
  3565.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3566.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3567.       src = (int *)back_cr;
  3568.       src1 = (int *)back_cb;
  3569.       
  3570.       for (rr = 0; rr < 8; rr++) {
  3571.     /*
  3572.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  3573.      * 8);
  3574.      */
  3575.     
  3576.     dest[0] = src[0];
  3577.     dest[1] = src[1];
  3578.     
  3579.     dest1[0] = src1[0];
  3580.     dest1[1] = src1[1];
  3581.     
  3582.     dest += half_row_incr;
  3583.     dest1 += half_row_incr;
  3584.     src += 2;
  3585.     src1 += 2;
  3586.       }
  3587.     } else {
  3588.       
  3589.       unsigned char *src1, *src2, *src1a, *src2a;
  3590.       unsigned char *dest, *dest1;
  3591.       dest = vid_stream->current->luminance + (row * row_size) + col;
  3592.       src1 = forw_lum;
  3593.       src2 = back_lum;
  3594.       
  3595.       for (rr = 0; rr < 16; rr++) {
  3596.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3597.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3598.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3599.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3600.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3601.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3602.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3603.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3604.     dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3605.     dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3606.     dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3607.     dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3608.     dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3609.     dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3610.     dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3611.     dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3612.     dest += row_size;
  3613.     src1 += 16;
  3614.     src2 += 16;
  3615.       }
  3616.       
  3617.       
  3618.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3619.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3620.       src1 = forw_cr;
  3621.       src2 = back_cr;
  3622.       src1a = forw_cb;
  3623.       src2a = back_cb;
  3624.       
  3625.       for (rr = 0; rr < 8; rr++) {
  3626.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3627.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3628.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3629.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3630.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3631.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3632.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3633.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3634.     dest += half_row;
  3635.     src1 += 8;
  3636.     src2 += 8;
  3637.     
  3638.     dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3639.     dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3640.     dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3641.     dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3642.     dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3643.     dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3644.     dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3645.     dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3646.     dest1 += half_row;
  3647.     src1a += 8;
  3648.     src2a += 8;
  3649.       }
  3650.     }
  3651.   }
  3652. }
  3653.  
  3654.  
  3655.  
  3656.  
  3657. /*
  3658.  *--------------------------------------------------------------
  3659.  *
  3660.  * ReconSkippedBlock --
  3661.  *
  3662.  *    Reconstructs predictive block for skipped macroblocks
  3663.  *      in B Frames.
  3664.  *
  3665.  * Results:
  3666.  *    No return values.
  3667.  *
  3668.  * Side effects:
  3669.  *    None.
  3670.  *
  3671.  *--------------------------------------------------------------
  3672.  */
  3673.  
  3674. static void
  3675. ReconSkippedBlock(source, dest, row, col, row_size,
  3676.           right, down, right_half, down_half, width)
  3677.   unsigned char *source;
  3678.   unsigned char *dest;
  3679.   int row, col, row_size, right, down, right_half, down_half, width;
  3680. {
  3681.   int rr;
  3682.   unsigned char *source2;
  3683.  
  3684.   source += ((row + down) * row_size) + col + right;
  3685.  
  3686.   if (width == 16) {
  3687.     if ((!right_half) && (!down_half)) {
  3688.     if (right & 0x1) {
  3689.       /* No alignment, use bye copy */
  3690.       for (rr = 0; rr < 16; rr++) {
  3691.         dest[0] = source[0];
  3692.         dest[1] = source[1];
  3693.         dest[2] = source[2];
  3694.         dest[3] = source[3];
  3695.         dest[4] = source[4];
  3696.         dest[5] = source[5];
  3697.         dest[6] = source[6];
  3698.         dest[7] = source[7];
  3699.         dest[8] = source[8];
  3700.         dest[9] = source[9];
  3701.         dest[10] = source[10];
  3702.         dest[11] = source[11];
  3703.         dest[12] = source[12];
  3704.         dest[13] = source[13];
  3705.         dest[14] = source[14];
  3706.         dest[15] = source[15];
  3707.         dest += 16;
  3708.         source += row_size;
  3709.       }
  3710.     } else if (right & 0x2) {
  3711.       /* Half-word bit aligned, use 16 bit copy */
  3712.       short *src = (short *)source;
  3713.       short *d = (short *)dest;
  3714.       row_size >>= 1;
  3715.       for (rr = 0; rr < 16; rr++) {
  3716.         d[0] = src[0];
  3717.         d[1] = src[1];
  3718.         d[2] = src[2];
  3719.         d[3] = src[3];
  3720.         d[4] = src[4];
  3721.         d[5] = src[5];
  3722.         d[6] = src[6];
  3723.         d[7] = src[7];
  3724.         d += 8;
  3725.         src += row_size;
  3726.       }
  3727.     } else {
  3728.       /* Word aligned, use 32 bit copy */
  3729.       int *src = (int *)source;
  3730.       int *d = (int *)dest;
  3731.       row_size >>= 2;
  3732.       for (rr = 0; rr < 16; rr++) {
  3733.         d[0] = src[0];
  3734.         d[1] = src[1];
  3735.         d[2] = src[2];
  3736.         d[3] = src[3];
  3737.         d += 4;
  3738.         src += row_size;
  3739.       }
  3740.     }
  3741.     } else {
  3742.       source2 = source + right_half + (row_size * down_half);
  3743.       for (rr = 0; rr < width; rr++) {
  3744.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3745.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3746.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3747.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3748.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3749.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3750.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3751.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3752.     dest[8] = (int) (source[8] + source2[8]) >> 1;
  3753.     dest[9] = (int) (source[9] + source2[9]) >> 1;
  3754.     dest[10] = (int) (source[10] + source2[10]) >> 1;
  3755.     dest[11] = (int) (source[11] + source2[11]) >> 1;
  3756.     dest[12] = (int) (source[12] + source2[12]) >> 1;
  3757.     dest[13] = (int) (source[13] + source2[13]) >> 1;
  3758.     dest[14] = (int) (source[14] + source2[14]) >> 1;
  3759.     dest[15] = (int) (source[15] + source2[15]) >> 1;
  3760.     dest += width;
  3761.     source += row_size;
  3762.     source2 += row_size;
  3763.       }
  3764.     }
  3765.   } else {            /* (width == 8) */
  3766.     assert(width == 8);
  3767.     if ((!right_half) && (!down_half)) {
  3768.       if (right & 0x1) {
  3769.     for (rr = 0; rr < width; rr++) {
  3770.       dest[0] = source[0];
  3771.       dest[1] = source[1];
  3772.       dest[2] = source[2];
  3773.       dest[3] = source[3];
  3774.       dest[4] = source[4];
  3775.       dest[5] = source[5];
  3776.       dest[6] = source[6];
  3777.       dest[7] = source[7];
  3778.       dest += 8;
  3779.       source += row_size;
  3780.     }
  3781.       } else if (right & 0x02) {
  3782.     short *d = (short *)dest;
  3783.     short *src = (short *)source;
  3784.     row_size >>= 1;
  3785.     for (rr = 0; rr < width; rr++) {
  3786.       d[0] = src[0];
  3787.       d[1] = src[1];
  3788.       d[2] = src[2];
  3789.       d[3] = src[3];
  3790.       d += 4;
  3791.       src += row_size;
  3792.     }
  3793.       } else {
  3794.     int *d = (int *)dest;
  3795.     int *src = (int *)source;
  3796.     row_size >>= 2;
  3797.     for (rr = 0; rr < width; rr++) {
  3798.       d[0] = src[0];
  3799.       d[1] = src[1];
  3800.       d += 2;
  3801.       src += row_size;
  3802.     }
  3803.       }
  3804.     } else {
  3805.       source2 = source + right_half + (row_size * down_half);
  3806.       for (rr = 0; rr < width; rr++) {
  3807.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3808.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3809.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3810.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3811.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3812.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3813.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3814.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3815.     dest += width;
  3816.     source += row_size;
  3817.     source2 += row_size;
  3818.       }
  3819.     }
  3820.   }
  3821. }
  3822.  
  3823.  
  3824.  
  3825. /*
  3826.  *--------------------------------------------------------------
  3827.  *
  3828.  * DoPictureDisplay --
  3829.  *
  3830.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3831.  *      image in lum plane. Updates past and future frame
  3832.  *      pointers. Dithers image. Sends to display mechanism.
  3833.  *
  3834.  * Results:
  3835.  *    Pict image structure locked if displaying or if frame
  3836.  *      is needed as past or future reference.
  3837.  *
  3838.  * Side effects:
  3839.  *    Lum plane pummelled.
  3840.  *
  3841.  *--------------------------------------------------------------
  3842.  */
  3843.  
  3844. static void
  3845. DoPictureDisplay(vid_stream)
  3846.   VidStream *vid_stream;
  3847. {
  3848.  
  3849.   /* Convert to colormap space and dither. */
  3850.  
  3851.   DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  3852.         vid_stream->current->Cb, vid_stream->current->display,
  3853.         vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  3854.  
  3855.   /* Update past and future references if needed. */
  3856.  
  3857.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  3858.     if (vid_stream->future == NULL) {
  3859.       vid_stream->future = vid_stream->current;
  3860.       vid_stream->future->locked |= FUTURE_LOCK;
  3861.     } else {
  3862.       if (vid_stream->past != NULL) {
  3863.     vid_stream->past->locked &= ~PAST_LOCK;
  3864.       }
  3865.       vid_stream->past = vid_stream->future;
  3866.       vid_stream->past->locked &= ~FUTURE_LOCK;
  3867.       vid_stream->past->locked |= PAST_LOCK;
  3868.       vid_stream->future = vid_stream->current;
  3869.       vid_stream->future->locked |= FUTURE_LOCK;
  3870.       vid_stream->current = vid_stream->past;
  3871.       ExecuteDisplay(vid_stream);
  3872.     }
  3873.   } else
  3874.     ExecuteDisplay(vid_stream);
  3875.  
  3876. }
  3877.  
  3878.  
  3879.  
  3880. /*
  3881.  *--------------------------------------------------------------
  3882.  *
  3883.  * ToggleBFlag --
  3884.  *
  3885.  *    Called to set no b frame processing flag.
  3886.  *
  3887.  * Results:
  3888.  *      No_B_Flag flag is toggled from present value to opposite value.
  3889.  *
  3890.  * Side effects:
  3891.  *      None.
  3892.  *
  3893.  *--------------------------------------------------------------
  3894.  */
  3895.  
  3896. void
  3897. ToggleBFlag()
  3898. {
  3899.   if (No_B_Flag) {
  3900.     No_B_Flag = 0;
  3901.   } else
  3902.     No_B_Flag = 1;
  3903. }
  3904.  
  3905.  
  3906.  
  3907.  
  3908. /*
  3909.  *--------------------------------------------------------------
  3910.  *
  3911.  * TogglePFlag --
  3912.  *
  3913.  *    Called to set no p frame processing flag.
  3914.  *
  3915.  * Results:
  3916.  *      No_P_Flag flag is toggled from present value to opposite value.
  3917.  *
  3918.  * Side effects:
  3919.  *      None.
  3920.  *
  3921.  *--------------------------------------------------------------
  3922.  */
  3923.  
  3924. void
  3925. TogglePFlag()
  3926. {
  3927.   if (No_P_Flag) {
  3928.     No_P_Flag = 0;
  3929.   } else
  3930.     No_P_Flag = 1;
  3931. }
  3932.